Java 8需要防御者(默认)方法

Java 8 Need of Defender (default) Methods

本问题已经有最佳答案,请猛点这里访问。

为什么我们需要Java 8中的接口中的防御方法,因为我们已经有了抽象类。

To add external functionality

但是抽象类是用于部分抽象的,因为我们的接口实际上是纯抽象类,所以为什么它们是接口内的默认方法?


将共享功能放在抽象基类中的问题是,类只能从一个基类派生。当您希望从多个基继承功能时,这是一个限制。

当需要从已经有基类的类实现接口时,通过抽象基类共享功能也可能成为一个问题。在这种情况下,您根本无法派生新的类,因为您必须选择两个基中的一个,当您可能需要两个基时。

默认方法可以优雅地解决这个问题:将公共实现放入默认方法中可以让您无限制地共享代码。

您可以将默认方法和继承抽象类之间的主要区别视为实现相同接口的兄弟对象之间水平共享功能的区别,或者继承相同基类的子对象之间垂直共享功能的区别。

下面是一个示例:考虑一个看起来像JDBC的ResultSet的接口,它有两种访问同一列的方法:按名称和按索引。接口可以这样编码:

1
2
3
4
5
6
7
8
9
10
11
interface ResultSet2 {
    int findColumn(String columnLabel);
    String getString(int index);
    long getLong(int index);
    default long getLong(String columnLabel) {
        return getLong(findColumn(columnLabel));
    }
    default String getString(String columnLabel) {
        return getString(findColumn(columnLabel));
    }
}

任何实施ResultSet2的人都必须实施三种方法,并免费获得其余两种方法。他们可以选择提供另一种实现,但这是可选的。


最初的目的是与C的扩展方法竞争。给定接口的核心方法,如get(), set() in List,可以定义和实现扩展方法(如sort())。

Java家伙争辩说,最好在接口本身上声明这些方法,而不是在外部位置;这样,方法可以被子类型重写,提供每个子类型的最佳实现。(他们还认为这些方法应该由接口作者控制;这是一个相当软的点)

虽然可以将默认方法添加到现有的接口中,但是破坏现有的第三方子类型是非常危险的,特别是对于非常老的类型,如List,在野外有很多子类型。因此,很少有默认方法被添加到现有的核心Java API中。看看这个问题。

对于新的接口,默认方法是API设计器非常有价值的工具。您可以向接口添加许多方便的方法,例如,Function.compose()。子类型只需要实现抽象/核心方法,而不是默认方法(但如果需要,它们可以实现)。

我不同意默认方法可以"进化"接口的观点。它们不改变接口的核心语义,它们只是方便的方法(以实例方法的形式)。

在设计接口时,应该预先仔细设计默认方法;如前所述,在后面添加默认方法是非常危险的。

C的扩展方法允许第三方添加便利方法;这是非常好的,并且没有理由Java为什么不能在将来引入类似的东西。


Defender方法背后的主要原因是能够用新功能扩展长的现有接口,而不破坏现有代码。特别是使用Java 8 LAMBA表达式,他们在集合接口上引入了许多新的方法,如Tyrable .Frach。通过提供默认方法,实现EDCOX1×0接口的现有类不必被修改以在Java 8环境中使用。