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

Java 8在接口上引入了默认和静态方法。 所以现在您可以在界面中使用默认或静态方法进行具体实现。

Java声称添加这两种新方法的原因是“确保与为这些接口的旧版本编写的代码的二进制兼容性”。

我的问题:

  • 为什么要扭曲界面原始概念,假设是完全抽象的,以支持现有的架构问题?
  • 除了类扩展多个接口的能力之外,使用抽象类和接口的新版本有什么区别?

Java声称添加这两种新方法的原因是“确保与为这些接口的旧版本编写的代码的二进制兼容性”。

这仅适用于默认方法(不是静态方法),省略了某些上下文。 来自兰茨州的Goetz :

默认方法的目的是使接口在初始发布后以兼容的方式进化。

主要目标是允许界面演化 ,即添加新方法。 如果将新方法添加到接口,则实现该接口的现有类将缺少实现,这将是不兼容的。 为了兼容,实现必须来自某个地方,因此它是由默认方法提供的。

为什么要扭曲界面原始概念,假设是完全抽象的,以支持现有的架构问题?

Java接口的主要目的是指定任何类都可以实现的契约 ,而不必改变它在类层次结构中的位置。 确实,在Java 8之前,接口纯粹是抽象的。 但是,这不是接口的基本属性。 即使包含默认方法,其核心界面仍然在实现类上指定合同。 实现类可以覆盖默认方法,因此该类仍然可以完全控制其实现。 (另请注意, 默认方法不能是最终的 。)

除了类扩展多个接口的能力之外,使用抽象类和接口的新版本有什么区别?

类扩展多个接口的能力与接口和抽象类之间的另一个差异密切相关,即接口不能包含状态。 这是允许多重inheritance的主要困难:如果一个超类在一个类的祖先中多次出现,那么这个超类的状态会出现一次还是几次? (这就是所谓的“钻石问题”。)

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

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

最后,接口中的静态方法不会影响类inheritance,也不是接口契约的一部分。 它们仅仅是以更方便的方式组织实用方法的一种方式。 例如,接口中静态方法的常见用法是静态工厂方法。 如果接口中不允许使用静态方法,则必须将静态工厂方法放在伴随类上。 允许接口中的静态方法允许这样的方法与接口本身分组,这样做是合适的。

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

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

这个新方法与使用抽象类(在某些情况下对于此问题是一个非常好的模式)之间的区别在于,您不能从多个抽象类inheritance。 但您可以轻松实现多个接口。

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