加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-14 05:31:20 所属栏目:Java 来源:网络整理
导读:我刚刚开始学习骆驼,我看到的第一件事就是 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
我刚刚开始学习骆驼,我看到的第一件事就是
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%的好处.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读