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

时间:2015-09-04 19:11:00

标签: java

为什么我们在java 8中的接口中需要Defender方法,因为我们已经有了抽象类。我在互联网上找到了各种答案,如:

  

添加外部功能

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

3 个答案:

答案 0 :(得分:2)

通过将功能放在抽象基类中来共享功能的问题在于,类可以从一个基类派生出来。当您希望从多个基础继承功能时,这是一种限制。

当您需要从已具有基类的类实现接口时,通过抽象基类共享功能也可能成为问题。在这种情况下,你根本无法推导出你的新课程,因为你必须选择两个基础中的一个,大概是你想要两者。

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

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

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

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的人都必须实施三种方法,并免费获得其余两种方法。他们可以选择提供替代实现,但这是可选的。

答案 1 :(得分:1)

防御方法背后的主要原因是能够在不破坏现有代码的情况下扩展具有新功能的长存在接口。特别是Java 8 lamba表达式,它们在集合接口上引入了许多新方法,如Iterable.forEach。通过提供默认方法,实现Iterable接口的现有类不必更改为在Java 8环境中使用。

答案 2 :(得分:1)

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

Java家伙认为,最好在界面本身而不是在外部地方声明这样的方法;这样可以通过子类型覆盖这些方法,从而为每个子类型提供最佳实现。 (他们还认为这些方法应该由接口作者控制;这是一个软点)

虽然默认方法可以添加到现有界面,但是破坏现有的第三方子类型是非常危险的,特别是对于像List这样具有大量子类型的非常古老的类型。因此,现有核心Java API中添加的默认方法非常少。请参阅this question

对于新接口,默认方法对于API设计者来说是一个非常有价值的工具。您可以为界面添加许多便捷方法,例如Function.compose()。子类型只需要实现抽象/核心方法,而不是默认方法(但如果他们愿意,可以使用它们)。

我不同意默认方法可以“发展”接口的想法。它们不会改变接口的核心语义,它们只是方便的方法(以实例方法的形式)。

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

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