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

前端之家收集整理的这篇文章主要介绍了java-8 – 为什么不能将@FunctionalInterface应用于SAM抽象基类前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我刚刚开始学习骆驼,我看到的第一件事就是
context.addRoutes(new RouteBuilder() {
        public void configure() {
            from("file:data/inBox?noop=true").to("file:data/outBox");
        }
    });

我(合理的IMHO)试图替换

context.addRoutes(()->from("file:data/inBox?noop=true").to("file:data/outBox"));

但这是无效的.

在我挖掘的时候,我发现,lambdas应用于功能界面(这被认为是接口限定),但是@FunctionalInterface注释只能应用于接口(足够公平),据我所知,没有抽象类的等效注释. RouteBuilder当然是一个抽象类.

为什么lambdas限于接口?

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

我可以理解,如果有一些限定词,如抽象方法必须公开,但我很失落地解释为什么上述是不合理的.

解决方法

这是JSR-335专家组中最困难和广泛辩论的决定之一.一方面,单抽象方法抽象类可能是羊羔的合理转换目标似乎是完全合理的.而且,如果你的心理模式是“羔羊只是紧密的匿名课”,那么这个理论是完全合理的.

然而,如果你拉一下这个字符串一段时间,你会意识到它拖延了很多复杂性和约束 – 为了少数用例.

这是拖拉的最糟糕的事情之一是在lambda体内的名称的含义,作为一个特殊情况,这个意思.在内部类的体内,有一个非常复杂的查找规则(“梳子查找”),因为内部类中的名称可以引用超类型的成员,或者可以从词汇环境中获取. (例如,许多bug和益智游戏都围绕着这个,而不是Outer.this,在内部类体中.)如果我们允许lambda转换来抽象SAM类,我们会有两个不好的选择;用内部类的可怕名称查找复杂性污染所有的lambdas,或允许转换为抽象类目标,但是限制访问,使得lambda主体不能引用基类的成员(这将导致其自身的混乱).我们得到的结果规则是非常干净的:除了lambda参数formals之外,lambda体内的名称(包括这只是一个名字)正好意味着它们在lambda体之外的意思.

将lambdas转换为内部类的另一个问题就是对象标识,以及随之而来的VM优化丢失.内部类创建表达式(例如,新的Foo(){})被保证具有唯一的对象标识.通过不强烈地对lambdas进行身份识别,我们释放虚拟机可以做出许多有用的优化,否则无法做到. (因此,lambda链接和捕获已经比匿名类更快了,而且我们还没有应用更深入的优化流程.)

此外,如果您有一个单抽象方法抽象类,并希望能够使用lambdas来创建它们,那么有一个简单的路径来实现这一点 – 定义一个以函数接口为参数的工厂方法. (我们在Java 8中为ThreadLocal添加了一个工厂方法,这样做)

“lambdas”的最后一个钉子就是方便的对象语法“,在对现有代码库进行了分析,并且使用了单抽象方法接口和抽象类之后,世界观点就来了.我们发现只有很小的比例是基于抽象类.把所有的羔羊与复杂性和性能问题混为一谈,只能使得不到1%的用途受益,这似乎是愚蠢的.所以我们做出了“勇敢”的决定,削减了这个用例,以获得其他99%的好处.

猜你在找的Java相关文章