‘Comparable 应该是’function界面’吗?
function接口的定义是“function接口是一个只有一个抽象方法的接口(除了Object的方法),因此代表了一个单一的function契约。”
根据这个定义,Comparable绝对是一个function界面。
lambda表达式的定义是“lambda表达式就像一个方法:它提供了一个forms参数列表和一个正文 – 一个表达式或块 – 用这些参数表示。”
lambda表达式的评估产生function接口的实例。
因此,lambda表达式的目的是通过实现function接口的单个function来创建function接口的实例。
即。 允许使用单个函数创建实例。
让我们来看看Comparable,这个界面是否设计用作单一function? 即。 它是否仅用于创建具有此单一function的实例?
Comparable的文档以“此接口对每个实现它的类的对象强加一个总排序。这个顺序称为类的自然顺序,类的compareTo方法被称为它的自然比较方法。”
上面的句子清楚地表明Comparable并不是设计用作单个函数,而是总是由一个类实现,它通过添加这个单个函数对其实例具有自然顺序。
这意味着它不是设计为使用lambda表达式创建的。
关键是我们不会有任何仅仅是可比较的对象,它意味着要实现,因此用作类的附加function。
那么,Java语言中是否有一种方法可以防止为Comparable创建lambda表达式? 接口的设计者是否可以决定这个接口是由一个类实现的,而不是通过使用lambda表达式作为这个单一方法的实例而被哄骗?
仅仅因为接口恰好具有单个抽象方法,所以不应将其视为function接口。
可能是,如果Java提供像NotFunctional这样的注释,编译器可以检查该接口是否不用于创建lambda表达式,例如。
@NotFunctional public interface Comparable { public int compareTo(T t); }
可以使用lambda表达式,其中需要具有单个抽象方法的接口的实例。 你写了,
仅仅因为接口恰好具有单个抽象方法,所以不应将其视为function接口。
这是完全正确的。 使用单个抽象方法是接口的结构属性,使其有资格使用lambda实现。 然而,一个接口是否有意义或在语义 上是否合理用lambda实现是一个不同的故事。 后者是@FunctionalInterface
注释的目的。 当它出现在接口上时,它表示该接口对于使用lambda实现有用的意图 。
值得注意的是, Comparable
接口缺少@FunctionalInterface
注释。
虽然使用lambda作为Comparable
实现可能是荒谬的,但似乎没有任何理由创建一种机制来防止这种情况发生。 看起来这样做不会成为错误的根源,这是开发这种机制的一个很好的理由。 相比之下, @FunctionalInterface
注释旨在引导程序员朝着正确的方向发展,而不是禁止可能存在错误但看起来并不真正有害的东西。
问题来自“方法”和“function”之间的细微差别。
函数的输出值仅取决于输入到该函数的参数。
但是,方法的输出取决于输入到函数的参数,但它也可能取决于对象的状态(实例变量)。
也就是说,任何函数都是方法,但并非所有方法都是函数。
例如,Comparator接口中的方法比较仅取决于其参数。 但是,Comparable接口中的方法compareTo取决于要比较的对象的状态,因此需要在类中实现。
因此,即使Comparable也有一个abstarct方法,从语义上讲它不应该被视为一个function接口。
好吧,除了讨论之外@FunctionalInterface
的信息性注释是多么有用(我很高兴Java 8并不要求它用于lambdas)。
Comparable
通常是类型的属性,因此不是function接口的良好候选者。 它被明确地描述为自然排序,并没有采用两个这个/那个参数。 所以这个属性使得任何方法都不可能在lambda上运行(similliar参数适用于几乎所有的接口)。
因此,集合设计者为该任务使用第二个接口: Comparator
,为此,实现它的lambda是一个非常自然的选择。
没有机制可以防止天真地使用不打算成为function接口的接口。 通过使用像@NotFunctional这样的附加注释,它可以由接口的设计者显式声明,它不应该用作lambda。 默认情况下,如果没有指定注释,则可以认为它与@Functional一样好,目前就是这种情况。