问题
我在Java 8中遇到了一个名为功能接口的新术语。
在使用lambda表达式时,我只能找到一个使用此接口的方法。
Java 8提供了一些内置的功能接口,如果我们想要定义任何功能接口,那么我们就可以使用@FunctionalInterface
注释。它将允许我们在接口中仅声明一个方法。
例如:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
除了使用lambda表达式之外,它在Java 8中有多大用处?
问题here与我提出的问题不同。在使用Lambda表达式时,它会问为什么我们需要功能接口。我的问题是:为什么使用功能接口而不是直接使用withlambda表达式?
#1 热门回答(90 赞)
@FunctionalInterface
annotation对于代码的编译时间检查很有用。除了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中没有其他用例。