Java 8最有用的功能之一是default接口上的新方法。引入它们的原因基本上有两个(可能还有其他原因):
default
Iterator.remove()
Iterable.forEach()
从API设计人员的角度来看,我希望能够在接口方法上使用其他修饰符,例如final。在添加便捷方法时,这将很有用,以防止在实现类时“意外”覆盖:
final
interface Sender { // Convenience method to send an empty message default final void send() { send(null); } // Implementations should only implement this method void send(String message); }
如果Sender已经上过课,以上是已经很普遍的做法:
Sender
abstract class Sender { // Convenience method to send an empty message final void send() { send(null); } // Implementations should only implement this method abstract void send(String message); }
现在,default并且final显然是相互矛盾的关键字,但是默认关键字本身并没有严格要求,因此我假设这种矛盾是有意的,以反映 “带有主体的类方法” (正义方法)和 “接口 ” 之间的细微差别。 带主体的方法” (默认方法),即我尚未理解的差异。
在一定的时间点,对于像修饰符的支持static和final接口方法上还没有充分探讨,援引布赖恩戈茨:
static
另一部分是我们要在接口中支持类构建工具的程度,例如最终方法,私有方法,受保护的方法,静态方法等。答案是:我们尚不知道
从2011年底开始,很明显,static增加了对接口方法的支持。显然,这为JDK库本身增加了很多价值,例如with Comparator.comparing()。
Comparator.comparing()
是什么原因final(也static final没有)没有使用Java 8接口?
static final
这个问题在某种程度上与Java8接口方法中不允许“同步”的原因有关?
了解默认方法的关键是,主要的设计目标是 接口演变 ,而不是“将接口转变为(中等)特性”。虽然两者之间存在一些重叠,并且我们试图适应后者所没有的障碍,但是从这种角度来看,最好理解这些问题。(还要注意,由于接口方法可以被多重继承的事实,无论什么意图,类方法 都 将与接口方法不同。)
默认方法的基本思想是:它是具有默认实现的接口方法,而派生类可以提供更具体的实现。而且由于设计中心是接口的演进,因此一个关键的设计目标是能够在 事后 以源兼容和二进制兼容的方式将默认方法添加到接口。
对于“为什么不是最终的默认方法”的答案太简单了,那就是主体将不再仅仅是默认的实现,而是唯一的实现。尽管答案太简单了,但它为我们提供了一个线索,表明这个问题已经朝着可疑的方向发展了。
最终接口方法令人质疑的另一个原因是它们为实现者带来了不可能的问题。例如,假设您有:
interface A { default void foo() { ... } } interface B { } class C implements A, B { }
在这里,一切都很好。C继承foo()自A。现在假定B已更改为具有foo默认值的方法:
C
foo()
A
B
foo
interface B { default void foo() { ... } }
现在,当我们进行重新编译时C,编译器将告诉我们它不知道要继承什么行为foo(),因此C必须重写它(并且A.super.foo()如果希望保留相同的行为,可以选择委托给它。)但是如果B已经违约了final,并且A不受作者的控制C吗?现在C已经无法挽回了。它不能不覆盖就进行编译foo(),但是foo()如果它是final in 则不能覆盖B。
A.super.foo()
这只是一个例子,但重点是方法的确定性实际上是一种工具,在单继承类(通常将状态与行为耦合)的世界中,比仅对行为做出贡献且可以相乘的接口更有意义。遗传。很难说出“最终实现器中可能还混入了其他什么接口”,而允许接口方法成为最终方法可能会导致这些问题(它们不会对编写接口的人大发雷霆,而会炸毁该接口的人)。尝试实施该功能的可怜用户。)
禁止使用它们的另一个原因是,它们不会代表您的意思。仅当类(或其超类)未提供方法的声明(具体或抽象)时,才考虑使用默认实现。如果默认方法是final方法,但是超类已经实现了该方法,则默认值将被忽略,这可能不是默认作者在声明它为final时所期望的。(此继承行为反映了设计中心对默认方法(接口演变)的反映。应该可以将默认方法(或对现有接口方法的默认实现)添加到已经具有实现的现有接口中,而无需更改实现该接口的现有类的行为,