问题

我在Java 8中遇到了一个名为功能接口的新术语。

在使用lambda表达式时,我只能找到一个使用此接口的方法。

Java 8提供了一些内置的功能接口,如果我们想要定义任何功能接口,那么我们就可以使用@FunctionalInterface注释。它将允许我们在接口中仅声明一个方法。

例如:

@FunctionalInterface
interface MathOperation {
    int operation(int a, int b);
}

除了使用lambda表达式之外,它在Java 8中有多大用处?

问题here与我提出的问题不同。在使用Lambda表达式时,它会问为什么我们需要功能接口。我的问题是:为什么使用功能接口而不是直接使用withlambda表达式?


#1 热门回答(90 赞)

@FunctionalInterfaceannotation对于代码的编译时间检查很有用。除了2774111595,default之外,你不能拥有多个方法,而是覆盖你的@FunctionalInterface中的方法Object或用作功能接口的任何其他接口的抽象方法。

但是你可以在没有这个注释的情况下使用lambdas,也可以覆盖没有@Override注释的方法。

来自docs

功能界面只有一个抽象方法。由于默认方法具有实现,因此它们不是抽象的。如果接口声明了一个覆盖java.lang.Object的公共方法之一的抽象方法,那么它也不会计入接口的抽象方法计数,因为接口的任何实现都将具有来自java.lang.Object或其他地方的实现。

这个可用于lambda表达式

public interface Foo {
  public void doSomething();
}

This不能在lambda表达式中使用

public interface Foo {
  public void doSomething();
  public void doSomethingElse();
}

但是这将给出编译错误

@FunctionalInterface
public interface Foo {
  public void doSomething();
  public void doSomethingElse();
}

"@FunctionalInterface"注释无效; Foo不是功能界面


#2 热门回答(48 赞)

功能接口具有单一功能。例如,具有单个方法'compareTo'的Comparable接口用于比较目的。 Java 8定义了许多功能接口**,这些接口在lambda表达式**中广泛使用。

引入了一个注释-@FunctionalInterface,当你注释的接口不是有效的功能接口时,它可用于编译器级错误。

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
 }

让我们尝试添加另一个抽象方法:

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
      int operationMultiply(int a, int b);
 }

上面将导致编译器错误,如下所示:

Unexpected @FunctionalInterface annotation
@FunctionalInterface ^ MathOperation is not a functional interface
multiple non-overriding abstract methods found in interface MathOperation

即使省略了@FunctionalInterface注释,功能接口也是有效的。它仅用于通知编译器在接口内强制执行单个抽象方法。

interface MathOperation {
      int operation(int a, int b);
 }

从概念上讲,功能界面只有一种抽象方法。由于默认方法具有实现,因此它们不是抽象的。由于默认方法不是抽象的,因此你可以根据需要随意添加默认方法到你的功能界面。**

以下是有效的功能界面:

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
      default void doSomeMathOperation(){
       //Method body
      }
 }

如果一个接口声明一个覆盖java.lang.Object的公共方法之一的抽象方法,那么该接口的抽象方法计数也不会计入**,因为该接口的任何实现都将具有java.lang.Object或其他地方的实现。

例如下面是一个有效的功能接口,即使它声明了两个抽象方法。为什么?因为其中一个抽象方法"equals()"具有与Object类中的公共方法相同的签名。

@FunctionalInterface
 interface MathOperation {
      int operation(int a, int b);
      @Override
      public String toString();  //Overridden from Object class
      @Override
      public boolean equals(Object obj); //Overridden from Object class
 }

虽然功能接口的预期用途是针对的lambda表达式,方法参考构造函数引用,但是它们仍然可以像任何接口一样使用匿名类,由类实现或由工厂方法创建。


#3 热门回答(9 赞)

Thedocumentation确实是目的之间的差异

信息性注释类型,用于指示接口类型声明旨在成为Java语言规范定义的功能接口。

和用例

请注意,可以使用lambda表达式,方法引用或构造函数引用创建功能接口的实例。

其措辞并不排除其他一般用例。由于主要目的是指示功能接口,因此你的实际问题归结为"除了lambda表达式和方法/构造函数引用之外还有其他用于功能性接口的用例吗?"

从功能接口是Java语言规范定义的Java语言构造,只有该规范可以回答这个问题:

JLS §9.8. Functional Interfaces

...除了通过声明和实例化类(第15.9节)创建接口实例的常规过程之外,还可以使用方法引用表达式和lambda表达式(第15.13节,第15.27节)创建功能接口的实例。

因此Java语言规范没有另外说明,该部分中提到的唯一用例是使用方法引用表达式和lambda表达式创建接口实例。 (这包括构造函数引用,因为它们在规范中被称为方法引用表达式的一种形式)。

所以在一句话中,没有,在Java 8中没有其他用例。


原文链接