Java 8中缺省方法与抽象类的接口

Interface with default methods vs Abstract class in Java 8

由于Java 8允许默认方式实现接口中的方法,所以在使用EDCOX1字段0的时间之间似乎存在混淆。

那么,什么时候应该使用与默认方法的接口,什么时候应该使用抽象类?抽象类在那个场景中仍然有用吗?


抽象类比默认方法实现(如私有状态)要多得多,但是对于Java 8,无论何时你都可以选择,你应该和守护者(AKA)一起。接口中的default方法。

对默认方法的约束是,它只能通过调用其他接口方法来实现,而不引用特定实现的状态。因此,主要的用例是更高级、更方便的方法。

这个新特性的好处在于,在您被迫使用一个抽象类作为方便方法之前,这样就将实现者限制为单一继承,现在您可以拥有一个真正干净的设计,只需界面和对程序员强制的最小实现工作量。

将EDCOX1的1种方法引入Java 8的最初动机是希望以lambda为导向的方法扩展集合框架接口,而不破坏现有的实现。尽管这与公共图书馆的作者更相关,但您可能会发现同样的功能在您的项目中也很有用。您有一个集中的地方可以添加新的便利性,并且不必依赖于类型层次结构的其余部分的外观。


有一些技术上的差异。抽象类与Java 8接口相比仍然可以做得更多:

  • 抽象类不能有构造函数。
  • 抽象类更加结构化,并且可以保持一种状态。
  • 概念上,防御方法的主要目的是在Java 8中引入新特性(如lambda函数)之后的向后兼容性。


    本文将对此进行描述。想一想关于托收的forEach

    1
    2
    List<?> list =
    list.forEach();

    The forEach isn’t declared by java.util.List nor the
    java.util.Collection interface yet. One obvious solution would be to
    just add the new method to the existing interface and provide the
    implementation where required in the JDK. However, once published, it
    is impossible to add methods to an interface without breaking the
    existing implementation.

    The benefit that default methods bring is that now it’s possible to
    add a new default method to the interface and it doesn’t break the
    implementations.


    如本文所述,

    Java 8中抽象类与接口的接口

    After introducing Default Method, it seems that interfaces and
    abstract classes are same. However, they are still different concept
    in Java 8.

    Abstract class can define constructor. They are more structured and
    can have a state associated with them. While in contrast, default
    method can be implemented only in the terms of invoking other
    interface methods, with no reference to a particular implementation's
    state. Hence, both use for different purposes and choosing between two
    really depends on the scenario context.


    这两个完全不同:

    默认方法是向现有类添加外部功能,而不更改它们的状态。

    抽象类是一种普通的继承类型,它们是要扩展的普通类。


    关于您对

    So when should interface with default methods be used and when should an abstract class be used? Are the abstract classes still useful in that scenario?

    Java文档提供了完美的答案。

    与接口相比的抽象类:

    Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation.

    However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.

    With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.

    每个用例的使用案例在下面的SE Post中进行了解释:

    接口和抽象类之间有什么区别?

    Are the abstract classes still useful in that scenario?

    对。它们仍然有用。它们可以包含非静态的、非最终的方法和属性(受保护的、私有的和公共的),这在Java-8接口中是不可能实现的。


    每当我们在抽象类和接口之间做出选择时,我们总是(几乎)更喜欢默认(也称为Defender或虚拟扩展)方法。

  • 默认方法结束了接口的经典模式,并结束了实现该接口中大多数或所有方法的伴生类。一个例子是Collection and AbstractCollection。现在,我们应该在接口本身中实现方法,以提供默认功能。实现接口的类可以选择重写方法或继承默认实现。
  • 默认方法的另一个重要用途是interface evolution。假设我有一个班级舞会:

    public class Ball implements Collection { ... }

  • 现在在Java 8中引入了一个新的特征流。我们可以使用添加到接口中的stream方法来获取流。如果stream不是默认方法,那么Collection接口的所有实现都将中断,因为它们不会实现这个新方法。向接口添加非默认方法不是source-compatible

    但是假设我们不重新编译该类并使用包含该类Ball的旧JAR文件。如果没有这个丢失的方法,类将加载得很好,可以创建实例,而且似乎一切都正常工作。但是如果程序在Ball的实例上调用stream方法,我们将得到AbstractMethodError。因此,使方法默认可以解决这两个问题。


    Java接口中的默认方法实现了接口的演进。

    对于现有的接口,如果希望在不破坏与旧版本接口的二进制兼容性的情况下向其添加方法,您手头上有两个选项:添加默认方法或静态方法。实际上,任何添加到接口的抽象方法都必须由实现该接口的类或接口实现。

    静态方法对于类是唯一的。默认方法对于类的实例是唯一的。

    如果向现有接口添加默认方法,则实现此接口的类和接口不需要实现它。他们可以

    • 实现默认方法,并重写已实现接口中的实现。
    • 重新声明使其成为抽象的方法(不带实现)。
    • 什么都不做(然后从实现的接口继承默认方法)。

    有关此主题的更多信息。


    Remiforax规则是不使用抽象类进行设计。你用界面设计你的应用程序。WATFEY是Java的版本,不管是什么语言。它以固体界面分离原理为基础。

    稍后可以使用抽象类来分解代码。现在使用Java 8,您可以直接在接口中执行它。这是一个设施,不是更多。


    when should interface with default methods be used and when should an
    abstract class be used?

    向后兼容性:假设您的接口是由数百个类实现的,修改该接口将强制所有用户实现新添加的方法,即使它对于实现您的接口的许多其他类来说可能不是必需的,而且它允许您的接口是一个功能性接口。

    事实和限制:

    1-只能在接口内声明,不能在类内声明,或抽象类。

    2-必须提供一个主体

    3-它不被认为是抽象的接口中使用的其他常规方法。


    在Java 8中,接口看起来像一个抽象类,尽管它们可能有一些差异,例如:

    1)抽象类是类,因此它们不限于Java中的接口的其他限制,例如抽象类可以具有状态,但不能在Java接口上具有状态。

    2)与默认方法和抽象类的接口之间的另一个语义区别是,您可以在抽象类内定义构造函数,但是不能用Java定义接口内的构造函数。


    Java接口中的默认方法更多地用于提供函数的哑实现,从而从声明所有抽象方法的痛苦中节省了该接口的任何实现类,即使它们只想处理一个。因此,接口中的默认方法在某种程度上更像是适配器类概念的替代品。

    然而,抽象类中的方法应该提供一个有意义的实现,任何子类只应在需要重写公共功能时重写该实现。


    请首先考虑打开/关闭原则。接口中的默认方法确实违反了它。这是Java中的一个坏特性。它鼓励糟糕的设计、糟糕的体系结构、低软件质量。我建议完全避免使用默认方法。

    问自己几个问题:为什么不能将方法放到抽象类中?那么您需要不止一个抽象类吗?然后想想你的班要负责什么。您确定要将所有方法放到单个类中,真的实现了相同的目的吗?也许你会区分几个目的,然后将你的类分成几个类,每个目的都有自己的类。