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


问题内容

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

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

我的问题:

  • 为什么为了支持现有的体系结构问题而扭曲应该完全抽象的接口原始概念?
  • 使用抽象类和新版本的接口之间的区别除了一个类具有扩展多个接口的能力之外,还有什么区别?

问题答案:

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

这仅适用于默认方法(不适用于静态方法),并且省略了某些上下文。从Lambda州Goetz出发:

默认方法的目的是使接口在最初发布后能够以兼容的方式发展。

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

为什么为了支持现有的体系结构问题而扭曲应该完全抽象的接口原始概念?

Java接口的主要目的是指定任何类都可以实现的协定,而不必更改其在类层次结构中的位置。的确,在Java
8之前,接口是纯抽象的。但是,这不是接口的基本属性。即使包括默认方法,接口的核心仍然会在实现类上指定一个约定。实现类可以覆盖默认方法,因此该类仍完全控制其实现。(还请注意,默认方法不能是final方法。)

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

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

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

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

最后,接口中的静态方法不会影响类的继承,也不是接口协定的一部分。它们仅仅是以更方便的方式组织实用程序的一种方式。例如,接口中静态方法的常见用法是静态工厂方法。如果接口中不允许使用静态方法,则必须将静态工厂方法放在伴随类中。允许在接口中使用静态方法时,可以将此类方法与接口本身组合在一起,如果合适的话。