Java 8 中的抽象类和接口之间有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22591499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are the differences between abstract classes and interfaces in Java 8?
提问by David says Reinstate Monica
In Java there used to be a subtle but important difference between abstract classes and interfaces: default implementations. Abstract classes could have them, interfaces could not. Java 8 though introduces default implementations for interfaces, meaning this is no longer the critical difference between an interface and an abstract class.
在 Java 中,抽象类和接口之间曾经有一个微妙但重要的区别:默认实现。抽象类可以有它们,接口不能。Java 8 虽然引入了接口的默认实现,这意味着这不再是接口和抽象类之间的关键区别。
So what is?
那么什么是?
As best as I can tell, the only remaining difference (besides perhaps some under the hood efficiency stuff) is that abstract classes follow traditional Java single-inheritance, whereas interfaces can have multiple-inheritance (or multiple-implementation if you will). This leads me to another question -
尽我所知,唯一剩下的区别(除了可能是一些底层效率的东西)是抽象类遵循传统的 Java 单继承,而接口可以具有多重继承(或多个实现,如果你愿意的话)。这让我想到了另一个问题——
How do the new Java 8 interfaces avoid the diamond Problem?
新的 Java 8 接口如何避免钻石问题?
采纳答案by skiwi
Interfaces cannot have state associated with them.
接口不能有与其关联的状态。
Abstract classes can have state associated with them.
抽象类可以具有与其关联的状态。
Furthermore, default methods in interfaces need not be implemented. So in this way, it will not break already existing code, as while the interface does receive an update, the implementing class does not need to implement it.
As a result you may get suboptimal code, but if you want to have more optimal code, then your job is to override the default implementation.
此外,不需要实现接口中的默认方法。所以通过这种方式,它不会破坏已经存在的代码,因为当接口确实收到更新时,实现类不需要实现它。
因此,您可能会得到次优代码,但如果您想拥有更优化的代码,那么您的工作就是覆盖默认实现。
And lastly, in case a diamond problem occurs, then the compiler will warn you, and youwill need to choose which interface you want to implement.
最后,如果出现菱形问题,编译器会警告您,您需要选择要实现的接口。
To show more about the diamond problem, consider the following code:
要显示更多关于菱形问题的信息,请考虑以下代码:
interface A {
void method();
}
interface B extends A {
@Override
default void method() {
System.out.println("B");
}
}
interface C extends A {
@Override
default void method() {
System.out.println("C");
}
}
interface D extends B, C {
}
Here I get the compiler error on interface D extends B, C
, that:
在这里我得到编译器错误interface D extends B, C
,即:
interface D inherits unrelated defaults for method() form types B and C
interface D inherits unrelated defaults for method() form types B and C
The fix is:
修复方法是:
interface D extends B, C {
@Override
default void method() {
B.super.method();
}
}
In case I wanted to inherit the method()
from B
.
The same holds for if D
were a class
.
如果我想继承method()
from B
.
这同样适用于 ifD
是 a class
。
To show even more about the difference between interfaces and abstract classes in Java 8, consider the following Team
:
为了进一步说明 Java 8 中接口和抽象类之间的区别,请考虑以下内容Team
:
interface Player {
}
interface Team {
void addPlayer(Player player);
}
You can in theory provide a default implementation of addPlayer
such that you can add players to for example a list of players.
But wait...?
How do I store the list of players?
The answer is that you cannot do that in an interface, even if you have default implementations available.
理论上,您可以提供一个默认实现,addPlayer
这样您就可以将玩家添加到例如玩家列表中。
可是等等...?
我如何存储玩家列表?
答案是您不能在接口中这样做,即使您有可用的默认实现。
回答by nosid
The definition of the diamond problemis a vague. There are all kinds of issues that can occur with multiple inheritance. Fortunately, most of them can be easily detected at compile-time, and the programming languages support simple solutions to work around these issues. Most of these problems are not even specific to the diamond problem. For example, conflicting definitions of methods can also occur without diamonds:
钻石问题的定义是模糊的。多重继承可能会出现各种问题。幸运的是,它们中的大多数可以在编译时轻松检测到,并且编程语言支持简单的解决方案来解决这些问题。大多数这些问题甚至都不是钻石问题所特有的。例如,如果没有菱形,也可能出现方法的冲突定义:
interface Bar {
default int test() { return 42; }
}
interface Baz {
default int test() { return 6 * 9; }
}
class Foo implements Bar, Baz { }
The specific problem with diamondsis the question of inclusivevs. exclusive. If you have a type hierarchy where Band Cderive from A, and Dderives from Band C, then the question is:
钻石的具体问题是inclusive与exclusive的问题。如果您有一个类型层次结构,其中B和C派生自A,而D派生自B和C,那么问题是:
- is Da B*and* a C(i.e. one type of A), or
- is Da B*or* a C(i.e. two types of A).
- 是Da B*and* a C(即A 的一种),或
- 是Da B*或* a C(即A 的两种类型)。
Well, in Java 8 the type Ahas to be an interface. So it makes no difference, because interfaceshave no state. It doesn't matter, that interfacescan define default methods, since they also have no state. They can invoke methods that have direct access to state. However, these methods are always implemented based on single inheritance.
好吧,在 Java 8 中,类型A必须是interface。所以它没有区别,因为接口没有状态。没关系,接口可以定义默认方法,因为它们也没有状态。他们可以调用可以直接访问状态的方法。但是,这些方法总是基于单继承来实现的。
回答by Philipp
Now that interfaces can contain executable code, lots of use-cases for abstract classes are taken over by interfaces. But abstract classes can still have member variables, while interfaces can't.
现在接口可以包含可执行代码,抽象类的许多用例都由接口接管。但是抽象类仍然可以有成员变量,而接口则不能。
The diamond problem is avoided by simply not allowing a class to implement two interfaces when both interfaces provide a default implementation for the same method with the same signature.
当两个接口为具有相同签名的相同方法提供默认实现时,通过简单地不允许类实现两个接口,可以避免钻石问题。
回答by Marco13
There have been some very detailed answers, but they seem to be missing one point that I at least consider as one of the very few justifications to have abstract classes at all:
已经有一些非常详细的答案,但他们似乎丢失了一个点,我至少认为是极少数的理由有抽象类的一个根本:
Abstract classes can have protectedmembers (and members with default visibility). Methods in interfaces are implicitly public.
抽象类可以具有受保护的成员(以及具有默认可见性的成员)。接口中的方法是隐式公开的。
回答by Ravindra babu
Java 8 though introduces default implementations for interfaces, meaning this is no longer the critical difference between an interface and an abstract class.
Java 8 虽然引入了接口的默认实现,这意味着这不再是接口和抽象类之间的关键区别。
Still there are few more critical differences. Refer to this post:
仍然存在一些更重要的差异。参考这个帖子:
Interface with default methods vs Abstract class in Java 8
How do the new Java 8 interfaces avoid the diamond Problem?
新的 Java 8 接口如何避免钻石问题?
Case 1:You are implementing two interfaces, which have same default
method, you have to resolve the conflict in your implementation class
案例1:您正在实现两个接口,它们具有相同的default
方法,您必须解决您的实现类中的冲突
interface interfaceA{
default public void foo(){
System.out.println("InterfaceA foo");
}
}
interface interfaceB{
default public void foo(){
System.out.println("InterfaceB foo");
}
}
public class DiamondExample implements interfaceA,interfaceB{
public void foo(){
interfaceA.super.foo();
}
public static void main(String args[]){
new DiamondExample().foo();
}
}
Above example produce below outout:
上面的例子产生以下输出:
InterfaceA foo
Case 2:You are extending a base class and implementing an interface with default method. Compiler resolves the diamond problem for you and you don't have to resolve it as in first example.
情况 2:您正在扩展基类并使用默认方法实现接口。Compiler 为您解决菱形问题,您不必像第一个示例中那样解决它。
interface interfaceA{
default public void foo(){
System.out.println("InterfaceA foo");
}
}
class DiamondBase {
public void foo(){
System.out.println("Diamond base foo");
}
}
public class DiamondExample extends DiamondBase implements interfaceA{
public static void main(String args[]){
new DiamondExample().foo();
}
}
Above example produce below output:
上面的例子产生以下输出:
Diamond base foo