首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Java中使用函数接口的真实示例

在Java中使用函数接口的真实示例
EN

Stack Overflow用户
提问于 2019-01-02 17:46:35
回答 5查看 6.2K关注 0票数 5

我知道函数式接口意味着您可以恰好/仅有一个抽象方法和一个以上的默认方法,但我想知道如何将其与在Java中使用函数式接口的真实示例/情况联系起来。

你能给出一个有效的情况/例子吗?

提前感谢!

EN

回答 5

Stack Overflow用户

发布于 2019-01-02 18:04:43

首先,Java的内置函数接口PredicateFunctionConsumer等使用了注释@FunctionalInterface

从另一方面来说,你可能想要创建你的自定义文件,如下所示:

代码语言:javascript
复制
@FunctionalInterface
public interface ThrowingConsumer<T> {
    void accept(T t) throws CustomException;
}

然后,您可以将其用作方法参数:

代码语言:javascript
复制
public <T, R> void doSomething(T value, ThrowingConsumer<T, R> consumer) {
    // ...
}

然后这样叫它:

代码语言:javascript
复制
doSomething(someValue, this::customConsumerMethodThrowingAnException);

值得一提的是,@FunctionalInterface不是必需的。对于任何符合the requirements的接口,编译器都能很好地工作。

编译器处理它的方式类似于处理@Override注释。即使没有它,代码也可以编译。但一旦添加,对于将来维护代码的人来说,它会使代码更清晰、更安全。

票数 6
EN

Stack Overflow用户

发布于 2019-01-02 18:41:37

在JDK8之前,我们总是有函数接口,但没有lambda、方法引用等。

从JDK8开始,它们为lambda表达式和方法引用提供了目标类型,从而具有更好的可读性和更紧凑的代码。

例如,在Java-8之前,如果您想提供在每次单击Button组件时都会执行的一些逻辑,您可以这样做:

代码语言:javascript
复制
 btn.setOnAction(new EventHandler<ActionEvent>() { 
       @Override
       public void handle(ActionEvent event) {
            System.out.println("Hello World!");
       }
 });

这是笨重,难以阅读和不够紧凑。因为根据定义,EventHandler是一个功能接口,也就是说,从jdk8开始,它有一个SAM,所以您现在可以这样做:

代码语言:javascript
复制
btn.setOnAction(event -> System.out.println("Hello World!"));

您只会看到您关心的代码部分,即当单击按钮时要执行的逻辑。

此外,由于我们可以使用函数接口作为lambda表达式和方法引用的目标类型,这在以下情况下将非常有用:

  • 将比较器传递给排序方法,例如List.sortStream.sortedCollections.sort等。
  • 传递代码块以在单独的线程中运行任务

等等。

同时保持代码的可读性、紧凑和简洁性。

函数接口在Java-stream API中广泛使用。

您没有理由创建自己的功能接口,除非java.util.function没有满足您要求的功能接口,或者功能接口的名称不具有可读性,因此您可以创建自己的功能接口。

还有一个@FunctionalInterface注释推荐使用,但在创建函数接口时不是必需的(标准库经常使用它)。

这使编译器能够检查带注释的实体是否是具有单个抽象方法的接口,否则会给出错误。

这对于能够在重构代码时捕获错误也很有帮助。

票数 4
EN

Stack Overflow用户

发布于 2019-01-02 17:59:19

它们提供的主要用途之一是,可以使用、lambda表达式、方法引用以及同时使用构造函数来创建函数接口的实例。例如,功能接口Sample定义为:

代码语言:javascript
复制
@FunctionalInterface
public interface Sample {
    void ab();
}

可以像下面这样用一行代码进行实例化:

代码语言:javascript
复制
Sample sample = () -> System.out.println("ab called");

然后在需要的地方调用,如:

代码语言:javascript
复制
sample.ab();

我将进一步引用java.util.function包中的Javadoc

函数接口可以在多个上下文中提供目标类型,例如赋值上下文、方法调用或强制转换上下文:

//赋值上下文谓词p= String::isEmpty;//方法调用上下文stream.filter(e -> e.getSize() > 10)...// Cast context stream.map((ToIntFunction) e -> e.getSize())...

此外,这样的接口可以用@FunctionalInterface注解来注解。

此注释并不要求编译器将接口识别为功能接口,但只是帮助捕获设计意图,并在中寻求编译器的帮助来识别意外违反设计意图的行为。

对于将概念用于现有的这种接口也是值得注意的,

无论接口声明中是否存在FunctionalInterface注释,编译器都会将满足函数接口定义的任何接口视为函数接口。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54004144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档