抽象类作为功能接口

gon*_*ard 36 java lambda functional-programming java-8

在java 8中,只有一个抽象方法的抽象类不是函数接口(JSR 335).

interface是一个功能界面:

public interface MyFunctionalInterface {
    public abstract void myAbstractMethod();
    public default void method() {
        myAbstractMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

但这abstract class不是:

public abstract class MyFunctionalAbstractClass {
    public abstract void myAbstractMethod();
    public void method() {
        myAbstractMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我不能使用抽象类作为lambda表达式和方法引用的目标.

public class Lambdas {
    public static void main(String[] args) {
        MyFunctionalAbstractClass functionalAbstractClass = () -> {};
    }
}
Run Code Online (Sandbox Code Playgroud)

编译错误是:The target type of this expression must be a functional interface.

为什么语言设计师强加了这个限制?

Mar*_*nik 33

自从Lambda项目开始以来,这一直是一个重要的话题,并且已经收到了很多想法.首席Java语言架构师Brian Goetz强烈支持将lambda视为一个函数,而不是一个对象.引用:

我相信,发展Java的最佳方向是鼓励更具功能性的编程风格.Lambda的作用主要是支持更多功能类库的开发和使用

我对Java的未来感到乐观,但为了向前发展,我们有时不得不放弃一些舒适的想法.Lambdas-are-functions打开了大门.Lambdas-are-objects关闭它们.我们希望看到这些门敞开.

这里是引用来源的链接,是Brian最近的帖子,它重申了相同的哲学观点,并用更多更实际的论点重申了这些观点:

使模型更简单为各种VM优化打开了大门.(抛弃身份在这里是关键.)功能是价值.将它们建模为对象会使它们比它们需要的更重,更复杂.

在将此用例丢弃到总线之前,我们进行了一些语料库分析,以发现与接口SAM相比,抽象类SAM的使用频率.我们发现在该语料库中,只有3%的lambda候选内部类实例将抽象类作为目标.其中大多数都适合简单的重构,你添加了一个构造函数/工厂,接受一个接口定位的lambda.

  • 我要补充一点,这是JSR-335早期阶段最激烈争论的话题之一.当我们第一次提出"仅接口"规则时,它似乎有风险.但由于现在已有几年的时间来解决,我绝对相信我们做了正确的事情.我们获得了显着的简单性和灵活性(以更好的性能和更灵活的未来语言演变的形式为所有用户带来),因为我们放弃了一些角落用例. (14认同)
  • @Dims Lambdas是匿名内部类的_not_语法糖,这就是重点.您有权要求相反的权利吗? (4认同)
  • 是的,实际上我认为这个特定方面是将Lambda项目的最高价值带到Java.看起来"正确"处于深层次,"更为严峻",甚至比我们在语言演变中看到的许多其他功能还要好 - 并且为Java的未来开辟了新的令人兴奋的方向. (3认同)