每个具有单个抽象方法的接口都应该是功能接口吗?

Every interface with a single abstract method should be a functional interface?

最近我开始了一个新项目,其中所有具有单个抽象方法的接口都用 @FunctionalInterface 注释。我经常看到人们在接口中添加另一个抽象方法后删除注释。我什么时候问过为什么?他们告诉我,一个不在公司的人告诉他们那样做。现在我不确定注释显然不会与 lambda 一起使用的接口是否是个好主意。

现在我看到一条有用的信息,就是人们甚至在服务中的服务中都在使用注释。我只是看起来像这样的代码:

@FunctionalInterface
public interface SomeService {
    void doSomething();
}

说明

每个只提供一个(抽象)方法的接口,即没有实现的接口,都是所谓的功能接口

明确或隐含。

注解 @FunctionalInterface@Override 一样,如果您想创建函数式接口,则为可选注解。

因此,如果您声明了一个接口 @FunctionalInterface,但它实际上有不止一个这样的方法,编译器会帮助您并防止编译出错。告诉你,你违背了自己的本意。

如果你没有注释,它会编译,但它不再是一个功能接口。这对您来说可能是一个错误,因为您的意图是创建一个功能界面。请注意,如果您实际上是在实际需要功能接口的环境中使用该接口,例如 lambda,那么一旦将另一个方法添加到该接口,它显然就不会再编译了。

这里有一些例子:

// is a functional interface
interface Foo {
    void bar();
}

// is a functional interface
@FunctionalInterface
interface Foo {
    void bar();
}

// is not a functional interface
interface Foo {
    void bar();
    void baz();
}

// does not compile
@FunctionalInterface
interface Foo {
    void bar();
    void baz();
}

使用

是为了让编译器、其他团队成员和未来的自己明白你的意图。这样,编译器可以帮助您发现错误,以防您搞砸了。

另一种情况可能是您在团队中工作并设计界面。如果您没有通过注释或 comment/documentation 将此接口明确标记为功能接口,则其他团队成员可能不知道您的意图并向其添加更多方法。

如果您是库设计者,即编写供其他外部人员使用的代码,这一点尤其重要。如果您标记您的界面 @FunctionalInterface,这是对他们的承诺,您打算保持它的状态。因此,他们可以安全地将其用于 lambda 等。不用担心一旦您将更新发送到您的库,他们的代码就会崩溃。

反之亦然。如果他们发现你的接口只有一个方法,但没有明确注释,他们会明白这并不意味着用作功能接口,尽管它目前是一个。因此,他们不会将它用于 lambda,尽管他们可以,因为您可能会在以后的更新中更改它。


详情

您可以在 JLS§9.8. Functional Interfaces:

中阅读准确的定义

A functional interface is an interface that has just one abstract method (aside from the methods of Object), and thus represents a single function contract. This "single" method may take the form of multiple abstract methods with override-equivalent signatures inherited from superinterfaces; in this case, the inherited methods logically represent a single method.

JLS§9.6.4.9. @FunctionalInterface

The annotation type FunctionalInterface is used to indicate that an interface is meant to be a functional interface (§9.8). It facilitates early detection of inappropriate method declarations appearing in or inherited by an interface that is meant to be functional.

It is a compile-time error if an interface declaration is annotated with @FunctionalInterface but is not, in fact, a functional interface.

Because some interfaces are functional incidentally, it is not necessary or desirable that all declarations of functional interfaces be annotated with @FunctionalInterface.

最后一段特别重要。 IE。您可能偶然创建了一个功能界面,并计划稍后向其添加更多内容。所以人们不应该误会这一点并将其与 lambda 一起使用,否则当您添加更多方法时,他们的代码稍后会崩溃。


备注

如前所述,@Override 标签的作用相同,但用于覆盖方法。所以你也可以在没有它的情况下覆盖方法。但是如果你使用它并且可能打错了字,即你实际上并没有覆盖某些东西,编译器会帮助你立即发现这个问题。

I'm not sure if it's a good idea to annotate interfaces that obviously will not be used with lambdas

不是。充其量,这是浪费时间。最坏的情况是,它具有误导性。

The documentation

[Use to indicate that the type] is intended to be a functional interface

如果您说它将 "obviously not" 在 lambda 中使用,那么使用标记您 do 期望使用明显矛盾的注释。