java-8 - 为什么@FunctionalInterface 不能应用于 SAM 抽象基类

标签 java-8 functional-interface

我刚开始学习 Camel ,我看到的第一件事是

    context.addRoutes(new RouteBuilder() {
        public void configure() {
            from("file:data/inbox?noop=true").to("file:data/outbox");
        }
    });

我(合理地恕我直言)尝试用
    context.addRoutes(()->from("file:data/inbox?noop=true").to("file:data/outbox"));

但这是无效的。

当我挖掘时,我发现 lambdas 适用于功能接口(interface)(如果接口(interface)符合条件,这是隐含的)但是 @FunctionalInterface 注释只能应用于接口(interface)(很公平),据我所知,抽象类没有等效的注释。 RouteBuilder 当然是一个抽象类。

为什么 lambdas 仅限于接口(interface)?

接口(interface)和使“功能类”不安全/不可预测/不合理的类之间的本质区别是什么?

我可以理解是否有一些限定符,例如抽象方法必须是公共(public)的,但是我无法解释为什么上述不合理。

最佳答案

Lambda 表达式定义的是函数而不是方法。它们之间显然存在技术关系,但在概念 View 和源代码级别的工作方式上有所不同。

例如。 lambda 表达式不会从它最终实现的类型继承成员。所以在你的情况下,即使 RouteBuilder 也行不通是一个函数式接口(interface),因为您的 lambda 表达式不会继承 from您要调用的方法。同理,this 的含义和 super与 lambda 表达式外部相同,并且不引用之后将代表函数的实例(即 RouteBuilder 实例)。

也就是说,扩展该功能以实现 abstract 并不是不合理的。行为类似于 interface 的类s 但这施加了一些难以检查的约束。虽然很容易验证一个类是否恰好有一个 abstract方法和可访问的无参数构造函数,该类也应该没有任何可变状态,并且该类的实例的构造也应该没有副作用,以便 JVM 可以自由缓存和重用 lambda实例并在不同的创建站点之间共享它们对程序的行为没有影响。

这很难验证,而且在大多数情况下,约束是不满足的,因为这就是使用 abstract class 的原因。而不是 interface首先。如果 lambda 表达式被定义为只是内部类的替代品,那么它就可以工作,因此不允许共享和重用实例,但这不是 lambda 表达式,即使它们被用作简单的内部类替代品很多情况下,不用考虑函数式编程……

关于java-8 - 为什么@FunctionalInterface 不能应用于 SAM 抽象基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31482093/

相关文章:

java - 为什么我需要一个函数式接口(interface)来使用 lambdas?

java - 特定HQL查询( hibernate )的连接错误预期路径

java - 用于 Arraylist 处理和调用不同方法的高效 Java 构造

java - Java8 中函数式接口(interface)的目的

java - 为什么在工厂方法和方法引用(单例/原型(prototype))中使用 lambda 时功能接口(interface)初始化不同?

java - 我可以创建一个函数接口(interface)来存储对包含任意数量参数的方法的方法引用吗?

java - 只遍历并获取文件名?

java - 有没有办法用自定义条件打破 Java Stream 并收集所有项目,直到条件与使用 Java 8 的列表匹配

java - 代理困惑的优雅解决方案

java - 如何在 UnaryOperator java 8 中使用引用方法