在接口中添加默认和静态方法的原因

Reason for adding default and static methods in interfaces

Java 8 在接口上引入了默认和静态方法。所以现在您可以在您的接口中有具体的实现,无论是使用默认方法还是静态方法。

Java声称添加这两种新方法的原因是"ensure binary compatibility with code written for older versions of those interfaces"。

我的问题:

问题是,您永远无法在不破坏兼容性的情况下使用新方法扩展接口。现有 classes 不会实现该方法,因此不会 运行 使用使用此方法的新版本代码。

这是 Java Class 库本身的一个主要问题,因为它无法在基本接口(如集合)中添加经常要求的方法。这是实现接口默认方法的主要驱动力。

这种新方法与使用抽象 class(在某些情况下这是解决此问题的一种很好的模式)之间的区别在于,您不能从多个抽象 class 继承。但是你可以轻松实现多个接口。

接口中的静态方法不太清楚,我认为它们是用来帮助你实现默认方法的(如果两个默认方法有相同的代码,它们都可以调用静态方法)。

The reason java claimed to add these 2 new kind of methods is "ensure binary compatibility with code written for older versions of those interfaces".

这仅适用于默认方法(不适用于静态方法)并省略了一些上下文。来自 Goetz, State of the Lambda:

The purpose of default methods ... is to enable interfaces to be evolved in a compatible manner after their initial publication.

主要目标是让接口进化,也就是增加新的方法。如果将新方法添加到接口,则实现该接口的现有 classes 将缺少实现,这将是不兼容的。为了兼容,一个实现必须来自某个地方,所以它由默认方法提供。

Why to distort the interface original concept that suppose to be fully abstract in order to support existing architectural problems?

Java 接口的主要目的是 specify a contract that any class can implement without having to alter its position in the class hierarchy. It's true that, prior to Java 8, interfaces were purely abstract. However, this is not an essential property of interfaces. Even when default methods are included, an interface at its heart still specifies a contract upon the implementing class. The implementing class can override default methods, so the class is still in complete control of its implementation. (Note also that default methods cannot be final。)

What is the difference between using an abstract class and the new version of the interface other than the ability of a class to extend multiple interfaces?

class扩展多个接口的能力与接口和抽象classes的另一个区别密切相关,即接口不能包含状态。这是允许多重继承的主要困难:如果 superclass 在 class 的祖先中出现多次,那个 superclass' 状态会只出现一次还是多次? (这就是所谓的"diamond problem.")

另一个区别是抽象 classes 可以通过使用受保护的和包私有的访问级别来定义要与子classes 共享的方法和字段,但不能与调用者共享。接口只能有 public 方法。

(在Java 9中,添加了对私有方法的支持。这对于接口的默认或静态方法之间的实现共享很有用。)

最后,接口中的静态方法不影响 class 继承,它们也不是接口契约的一部分。它们只是一种以更方便的方式组织实用方法的方式。例如,接口中静态方法的常见用途是用于静态工厂方法。如果接口中不允许使用静态方法,则必须将静态工厂方法放在伴随 class 上。在接口中允许静态方法可以让这些方法在适当的时候与接口本身组合在一起。