我知道一个功能接口意味着您只能/完全只有一种抽象方法和一种以上的默认方法,但是我想知道如何将其与使用功能接口的真实示例/情况相关联。 Java。
您能提供一个有效的情况/例子吗?
谢谢!
答案 0 :(得分:4)
首先,批注@FunctionalInterface
由Java的内置功能接口Predicate
,Function
,Consumer
等使用。
从另一方面来说,您可能想要创建自定义对象,如下所示:
@FunctionalInterface
public interface ThrowingConsumer<T> {
void accept(T t) throws CustomException;
}
然后您可以将其用作方法参数:
public <T, R> void doSomething(T value, ThrowingConsumer<T, R> consumer) {
// ...
}
然后这样称呼它:
doSomething(someValue, this::customConsumerMethodThrowingAnException);
值得一提的是,@FunctionalInterface
不是必需的。满足任何the requirements接口的编译器都可以。
编译器以类似于处理@Override
批注的方式来处理它。代码即使没有也可以编译。但是一旦添加,它对于将来将要维护代码的人来说,使代码更清晰,更安全。
答案 1 :(得分:3)
它们提供的主要用途之一是可以使用 lambda表达式和方法引用 来创建功能接口的实例。以及同时使用构造函数例如,功能接口Sample
定义为:
@FunctionalInterface
public interface Sample {
void ab();
}
可以像单行代码一样简单地实例化:
Sample sample = () -> System.out.println("ab called");
,然后在需要的地方按以下方式调用:
sample.ab();
我将进一步引用java.util.function
包中的Javadoc:
功能接口可以在多种情况下提供目标类型, 例如分配上下文,方法调用或广播上下文:
// Assignment context Predicate<String> p = String::isEmpty; // Method invocation context stream.filter(e -> e.getSize() > 10)... // Cast context stream.map((ToIntFunction) e -> e.getSize())...
此外,此类界面可以使用@FunctionalInterface
注释进行注释。
此注释不是编译器识别的必需条件 接口作为功能接口,但仅是捕获的辅助工具 设计意图,并在确定 意外违反设计意图。
将概念与现有的此类接口配合使用也很重要,
无论接口声明中是否存在FunctionalInterface
批注,编译器都将满足功能接口定义的任何接口视为功能接口。
答案 2 :(得分:2)
在JDK8之前,我们一直都有功能接口,但没有lambda,方法引用等。
从JDK8开始,它们为lambda表达式,方法引用提供了目标类型,从而具有更好的可读性和更紧凑的代码。
例如,在Java-8之前,如果您想提供每次单击Button
组件时将执行的某些逻辑,则可以这样做:
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
这很笨重,难以阅读且不够紧凑。因为根据定义,EventHandler
是一个功能接口,即从jdk8起它具有SAM
,您现在可以这样做:
btn.setOnAction(event -> System.out.println("Hello World!"));
您只看到您关心的部分代码,即单击按钮时要执行的逻辑。
此外,由于我们可以将函数接口用作lambda表达式和方法引用的目标类型,因此在以下情况下将非常有用:
List.sort
,Stream.sorted
,Collections.sort
等等...
同时保持代码的可读性,紧凑性和简洁性。
功能接口在Java流API中得到了广泛使用。
您没有理由创建自己的功能接口,除非没有java.util.function
满足您要求的接口,或者该功能接口的名称不易读,因此您可以创建自己的功能接口。
还有一个@FunctionalInterface
注释,建议您在创建功能接口时使用(但标准库经常使用此注释)。
这使编译器能够检查带注释的实体是否是具有单个抽象方法的接口,否则会产生错误。
这在重构代码时能够捕获错误也很有帮助。
答案 3 :(得分:1)
标记为FunctionalInterface
的接口可确保在期望具有适当参数和返回类型的lambda表达式的环境中使用。除此之外,它们没有任何用途。可能会有一些优化,但是在所有情况下都没有关系
答案 4 :(得分:1)
Lambda是Functional接口的实现...因此,将隐式地(通过编译器或在运行时)或显式地(通过代码...赋值)使用它们。实际示例是