Java 8中Default或Defender方法的目的

时间:2013-11-15 09:59:03

标签: java java-8 default-method

Java 8包含一个名为Defender methods的新功能,允许在接口中创建默认方法实现。

现在首先,对于Java中所有精简程序员来说,这是一个巨大的范式转换。我查看了Brain Goetz提供的JavaOne 13演示文稿,他正在讨论集合库中新的stream()parallelStream()实现。

为了在Collection界面中添加新方法,他们不能在不破坏以前版本的情况下添加新方法。所以他说,为了迎合这一点,我们增加了默认方法的新功能。

public interface SimpleInterface {
  public void doSomeWork();

  //A default method in the interface created using "default" keyword
  default public void doSomeOtherWork(){
    System.out.println("DoSomeOtherWork implementation in the interface");
  }
}

现在我的问题基本上是默认方法只是在需要向接口添加新方法而不破坏客户端代码时才有用吗?或者还有一些其他用途吗?

5 个答案:

答案 0 :(得分:57)

除了可以在将来的版本中向接口添加方法之外,即使有多个方法,也有一个重点是允许interface保留功能接口

功能接口只有一个非默认的抽象方法,可以通过lambda表达式实现。一个示例是the Predicate interface,其中只有一个抽象方法(test),同时提供用于否定Predicate或将其与另一个Predicate组合的默认方法。如果没有默认方法,这些方法必须在另一个实用程序类中提供,例如pre-Java 8 Collections类(因为您不希望放弃对此类interface进行lambda实现的可能性)。

答案 1 :(得分:20)

正如你所说,主要动机允许现有界面的演变。

然而有理由说你也想在全新的界面中使用它们:

一个这样的原因是可以使用接口的其他(非默认)方法轻松实现的方法。使用default方法可以减少对Foo - interface / AbstractFoo - 基础实现组合的需求(例如,请参阅AbstractList)。

虽然这不会创建一个全新的字段,但这意味着您可以拥有最终用户友好的界面(包含许多有用的方法),同时仍然保持其易于实现。

答案 2 :(得分:1)

接口存在问题,他们没有对扩展开放,这意味着如果需要向接口添加新方法,则会破坏这些接口的现有实现。因此,必须实现该接口的所有类必须为新添加的方法提供实现,即使不需要该方法也是如此。因此,接口不容易发展。

我想到的一个例子是Hadoop的Java MapReduce API,它在0.20.0版本中被更改为支持接口上的抽象类,因为它们更容易发展。这意味着,可以将一个新方法添加到抽象类(使用默认实现),而不会破坏该类的旧实现。

随着Java 8的发布,现在可以在接口中添加默认方法,从而使它们也更容易进化。通过向接口添加默认方法,添加新方法,即使是接口也不会破坏预先存在的代码。

答案 3 :(得分:0)

  1. 默认方法使函数式编程概念成为可能。对于函数式编程类型代码,我们只需要一个抽象方法。
  2. 在接口中添加方法也不会使所有实现接口的类成为必需。简化了编码实践

答案 4 :(得分:0)

<块引用>

对于在 Collection 接口中添加新方法,他们不能有 只是添加了一个新方法,而不会破坏以前的版本。

是的,他们本可以这样做,但让我们从 API 设计者的角度思考,例如Collection Library 被一些库使用,如 apache-commons、guava 等,而许多 java 项目都使用它们。现在想象一下,仅仅在 Collection 接口中添加一个新方法就会破坏整个项目链。

<块引用>

现在我的问题基本上是默认方法只是有帮助 当需要在不中断客户端的情况下向接口添加新方法时 代码?或者它还有其他用途吗?

默认方法的动机/需求

API 以兼容方式演变

  • 引入默认方法的最初目的是使集合库向后兼容。这个库被建模为一个深层次的接口,包括集合、列表、映射和集合等重要成员。它们需要得到丰富,以使 lambda 表达式真正对日常编程有用。
<块引用>

为了使集合库 lambda 丰富,Java 架构师可以拥有 重构它们以支持 lambda 但这远不是一个好的 解决方案,因为它会破坏所有现有的 Java 部署和 无数的第三方库扩展了集合层次结构

相反,Java 架构师考虑引入默认方法功能以实现向后兼容性。

默认方法的用例

  • 一个重要的用例是在 Java 中辅助 functional thinking。具有默认方法的函数式接口是纯行为结构。它不能保持状态。这使您的思维与函数式编程保持一致,并允许您利用编程模型所提供的功能

  • 可选方法:java中有一些类实现了一个接口,但留下了空的方法实现,例如Iterator interface。它定义了 hasNext 和 next 以及 remove 方法。在 Java8 之前 remove 被忽略,因为用户不想使用该功能。因此,许多实现 Iterator 接口的类都有空的 for remove 实现,即 unnecessary boiler plate code。使用默认方法,我们可以为此类方法提供默认实现,因此具体类不需要显式提供空实现。

  • 默认方法有助于解决行为的多重继承。在 Java8 之前,只支持 Type 的多重继承,现在在默认方法的帮助下,我们可以拥有多重继承行为。 例如 Java 8 有三个规则来解决由 不明确时的多重继承:

    • 首先,类或超类中的显式方法声明优先于任何默认方法声明。
    • 否则,选择最具体的默认提供接口中具有相同签名的方法。
    • 最后,如果仍然存在冲突,您必须显式覆盖默认方法并选择您的类应该选择哪一个。

结论 默认方法提供了一种全新的对象设计方法。

参考资料:

Java8 In Action

Functional Java: A Guide to Lambdas and Functional Programming in Java 8