Java 8 接口默认方法与抽象类中的非抽象方法 - 两者之间是否有任何差异(除了 iface 的差异 - 类、可见性等)
默认方法不是 Java 的退步,意味着它违背了 Java 多年来一直宣传的本质吗?!
Java 8 接口默认方法与抽象类中的非抽象方法 - 两者之间是否有任何差异(除了 iface 的差异 - 类、可见性等)
默认方法不是 Java 的退步,意味着它违背了 Java 多年来一直宣传的本质吗?!
抽象类中的非抽象方法将在其具体子类调用 super() 时被调用(如果它被覆盖)。所以有多种可能。如果方法没有被覆盖,那么超类方法将被执行。如果我们在具体的子类方法中使用 super() ,那么将执行被超类方法覆盖的方法。
Java 8 接口的默认方法完全不同。它为开发人员提供了在实现类中实现或不实现该方法的选择。如果该功能没有实现,那么只有在那时才会执行默认方法。
可能的用例:
JDK 库中这个新特性最重要的用例是在不破坏现有实现者的情况下扩展现有接口的可能性:向接口添加新的抽象方法将需要所有实现类来实现该新方法。(来源)
要记住的重要一点是,默认方法无法访问状态,只能访问行为。它实际上是定义合理的默认行为的好地方。
想象一下你有一个界面:
public interface Plant {
enum Pace { FAST, SLOW; }
void grow(Pace pace);
void growFast();
void growSlow();
}
提供默认行为似乎是合理的:
default void growFast() { grow(Pace.FAST); }
default void growSlow() { grow(Pace.SLOW); }
这是一个简单的示例,但显示了默认方法如何有用。在这种情况下,方式growSlow
或growFast
行为是接口契约的一部分,因此在接口级别定义它们的行为是有意义的。
然而,界面没有假设“种植植物”的动作是如何实现的。这可以在抽象类中定义。
首先,默认方法允许您在不破坏现有实现的情况下向接口添加新方法。
还举一个Collections
类的例子,它是Collection
接口权的实用程序类。
因此,使用默认方法,我们现在可以将所有实用程序方法作为默认实现移动到Collection
自身中,这比为此类实用程序创建单独的类更有意义。
abstract
此外,您将能够从多个接口继承方法,这是使用普通类无法完成的。
最大的区别是构造函数可能在匿名类中运行,可能带有检查异常。这可以防止匿名类成为函数式接口,进而使它们无法用作 lambda 表达式的基础。
主要区别在于:Java 8 接口的默认方法是公共的,而抽象类的非抽象(具体)方法可以定义为公共、受保护或私有。Lambda 表达式是在 Java 8 中引入的,要使用 lambda 特性,我们需要默认方法(以保持向后兼容性),抽象类的非抽象方法不能达到目的。