关于接口:Java是否有计划默认方法(java8)替代抽象类?

Does Java have plan that default method (java8) Substitute for Abstract Class?

Java是否有EDOCX1 0替代EDCOX1?1的计划?我找不到一个真正的案例来使用默认方法而不是抽象方法?


没有这样的计划,您可以通过比较已经记录的意图得出,这与此类计划的含义不同:

斯图尔特·马克斯写道:

The main goal is to allow interface evolution, that is, the addition of new methods. If a new method is added to an interface, existing classes that implement the interface would be missing an implementation, which would be incompatible. To be compatible, an implementation has to come from somewhere, so it is provided by default methods.

The main intent of a Java interface is to 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.)

布莱恩·戈茨写道:

The proximate reason for adding default methods to interfaces was to support interface evolution, …

Here are some use cases that are well within the design goals:

  • Interface evolution. Here, we are adding a new method to an existing interface, which has a sensible default implementation in terms of existing methods on that interface. An example would be adding the forEach method to Collection, where the default implementation is written in terms of the iterator() method.

  • "Optional" methods. Here, the designer of an interface is saying"Implementors need not implement this method if they are willing to live with the limitations in functionality that entails". For example, Iterator.remove was given a default which throws UnsupportedOperationException; since the vast majority of implementations of Iterator have this behavior anyway, the default makes this method essentially optional. (If the behavior from AbstractCollection were expressed as defaults on Collection, we might do the same for the mutative methods.)

  • Convenience methods. These are methods that are strictly for convenience, again generally implemented in terms of non-default methods on the class. The logger() method in your first example is a reasonable illustration of this.

  • Combinators. These are compositional methods that instantiate new instances of the interface based on the current instance. For example, the methods Predicate.and() or Comparator.thenComparing() are examples of combinators.

请注意,这些对象并不是抽象类的主域,比如提供一个框架实现。除了技术上的差异之外,抽象类在语义上也是不同的,因为它们承担着有关如何实现功能的设计决策,即使是与default方法的接口也不应如此。例如,一个众所周知的例子是List接口,对于它,存在两个基本上不同的抽象类:AbstractListAbstractSequentialList,并且子类的选择或者实现List完全不同不应该被接口所取消。因此,List接口定义了契约,不能替代提供特定基础实现的抽象类。


其他答案和附加材料的链接已经充分涵盖了接口和抽象类之间的技术差异。没有被很好地覆盖的是为什么要使用一个而另一个。

考虑使用Java中的类或接口的两种不同方式:作为调用方或子类。调用方具有对象引用,可以调用public方法并通过该引用访问public字段。子类也可以访问、调用和重写超类的protected成员。类可以有protected成员,但接口不能。

一个常见的问题似乎是,既然我们有了默认的方法,为什么我们需要抽象类?默认方法是接口向调用方显示的内容的一部分。类上的protected方法对调用方不可用;它只对子类可用。因此,如果希望与子类共享实现,那么可以使用类(或抽象类)并定义protected成员和字段。

protected机制允许类与子类通信,这与它与调用方通信的方式不同。

但是OP提出了一个相反的问题:为什么使用默认方法而不是抽象类?在您实际有选择的情况下(即,抽象不需要状态或保护方法,或者抽象类具有接口不需要的任何东西),使用默认方法的接口比抽象类的约束要少得多。只能从一个类继承;可以从多个接口继承。因此,具有默认方法的接口可以表现为无状态特性或混合,允许您从多个接口继承行为。

由于接口和抽象类用于不同的目的,因此没有删除或替换任何内容的计划。


默认方法不能替换抽象类,因为抽象类可以(而且经常)有字段。接口只能包含行为,而不是状态,将来不可能改变,因为Java中的多态继承被视为是正确的或错误的。

他们也可以有final方法,这是另一种你不能用default方法模拟的东西。

如果有的话,使用默认方法的接口类似于特征而不是抽象类,但是匹配并不完美。使用界面作为特征是必须非常仔细地做的事情,并且要知道它们的局限性。(例如,任何实现类都可以重写default方法,这可能会破坏特性。)

更多信息。


引入接口中默认方法的原因之一是允许向JDK接口添加新方法。

如果没有这个特性,一旦用接口的特定版本编译了一个类,就不能向这个接口添加新方法。使用接口中的默认方法,可以更改功能接口。