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