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

10

Java 8引入了接口上的默认方法和静态方法。因此,您现在可以在接口中使用默认方法或静态方法来实现具体的功能。

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

我的问题:

  • 为什么要扭曲接口的原始概念以支持现有的架构问题?
  • 除了类能够实现多个接口之外,使用抽象类和新版本的接口有何区别?

2
可能是 https://dev59.com/EmEh5IYBdhLWcg3wTBxc 的重复问题。 - FThompson
1
@Vulcan 我的问题是针对使用Java 8更新而不是抽象和接口之间的区别。 - Hussein Zawawi
2个回答

12
Java宣称添加这两种新方法的原因是“确保与旧版本接口编写的代码的二进制兼容性”。这仅适用于默认方法(而不是静态方法),其中省略了一些上下文。从Goetz,Lambda状态中可以得出:默认方法的目的是“使接口能够在其初始发布后以兼容的方式进行演进”,主要目标是允许接口演化,即添加新方法。如果向接口添加新方法,则实现接口的现有类将缺少实现,这将是不兼容的。为了兼容,必须提供实现,因此提供默认方法。为什么要扭曲原本应完全抽象的接口概念,以支持现有的架构问题呢?
Java接口的主要目的是指定一个契约,任何类都可以实现它,而不必改变其在类层次结构中的位置。确实,在Java 8之前,接口是纯粹抽象的。然而,这并不是接口的本质属性。即使包括默认方法,接口在其核心仍然指定了实现类的契约。实现类可以重写默认方法,因此类仍然完全控制其实现。(还要注意默认方法不能是final。

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

一个类可以扩展多个接口的能力与接口和抽象类的另一个区别密切相关,即接口不能包含状态。这是允许多重继承的主要困难:如果一个超类在类的祖先中出现多次,那么该超类的状态会出现一次还是几次?(这就是所谓的“菱形问题”。)
另一个区别是抽象类可以使用protected和包级私有访问级别定义方法和字段,以便与子类共享,但不与调用者共享。接口只能有公共方法。(在Java 9中,添加了对私有方法的支持。这对于在接口的默认或静态方法之间进行实现共享非常有用。)
最后,接口中的静态方法不会影响类继承,也不是接口的一部分。它们只是一种更方便地组织实用方法的方式。例如,在接口中使用静态方法的常见用途是用于静态工厂方法。如果接口中不允许静态方法,则必须将静态工厂方法放在伴随类中。允许在接口中使用静态方法使得这些方法与接口本身分组成为可能,当适用时。

2
问题在于,如果你在接口中添加新的方法,就会破坏兼容性。现有的类将不会实现该方法,因此不能运行使用该方法的新代码版本。
这对Java类库本身来说是一个主要问题,因为它无法在基本接口中添加常用方法(如集合)。这是实现接口默认方法的主要驱动力。
这种新方法与使用抽象类(在某些情况下是一种非常好的模式)的区别在于,你不能从多个抽象类继承,但可以轻松地实现多个接口。
接口中的静态方法不太清晰,我认为它们是为了帮助你实现默认方法(如果两个默认方法具有相同的代码,则它们都可以调用静态方法)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接