何时使用:Java 8+ 接口默认方法与抽象方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19998454/
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
When to use: Java 8+ interface default method, vs. abstract method
提问by Narendra Pathai
Java 8 allows for default implementation of methods in interfaces called Default Methods.
Java 8 允许在称为Default Methods 的接口中默认实现方法。
I am confused between when would I use that sort of interface default method
, instead of an abstract class
(with abstract method(s)
).
我在何时使用那种interface default method
, 而不是abstract class
(with abstract method(s)
)之间感到困惑。
So when should interface with default methods be used and when should an abstract class (with abstract method(s)) be used? Are the abstract classes still useful in that scenario?
那么什么时候应该使用带有默认方法的接口,什么时候应该使用抽象类(带有抽象方法)?抽象类在那种情况下仍然有用吗?
采纳答案by Marko Topolnik
There's a lot more to abstract classes than default method implementations (such as private state), but as of Java 8, whenever you have the choice of either, you should go with the defender (aka. default
) method in the interface.
抽象类比默认方法实现(例如私有状态)要多得多,但是从 Java 8 开始,无论何时您可以选择其中之一,您都应该使用接口中的防御者(又名。default
)方法。
The constraint on the default method is that it can be implemented only in the terms of calls to other interface methods, with no reference to a particular implementation's state. So the main use case is higher-level and convenience methods.
默认方法的限制是它只能在调用其他接口方法的情况下实现,而不能引用特定实现的状态。所以主要用例是更高级别和方便的方法。
The good thing about this new feature is that, where before you were forced to use an abstract class for the convenience methods, thus constraining the implementor to single inheritance, now you can have a really clean design with just the interface and a minimum of implementation effort forced on the programmer.
这个新特性的好处是,在之前你被迫使用抽象类来提供方便的方法,从而将实现者限制为单一继承,现在你可以拥有一个非常干净的设计,只有接口和最少的实现强加给程序员的努力。
The original motivation to introduce default
methods to Java 8 was the desire to extend the Collections Framework interfaces with lambda-oriented methods without breaking any existing implementations. Although this is more relevant to the authors of public libraries, you may find the same feature useful in your project as well. You've got one centralized place where to add new convenience and you don't have to rely on how the rest of the type hierarchy looks.
将default
方法引入Java 8的最初动机是希望在不破坏任何现有实现的情况下使用面向 lambda 的方法扩展集合框架接口。尽管这与公共库的作者更相关,但您可能会发现相同的功能在您的项目中也很有用。您有一个集中的地方可以添加新的便利,并且您不必依赖类型层次结构的其余部分的外观。
回答by Masudul
This is being described in this article. Think about forEach
of Collections.
这在本文中进行了描述。想想forEach
收藏。
List<?> list = …
list.forEach(…);
The forEach isn't declared by
java.util.List
nor thejava.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.
forEach 还没有被声明,
java.util.List
也没有被java.util.Collection
接口声明。一个明显的解决方案是将新方法添加到现有接口并在 JDK 中需要的地方提供实现。但是,一旦发布,就不可能在不破坏现有实现的情况下向接口添加方法。默认方法带来的好处是现在可以向接口添加新的默认方法并且不会破坏实现。
回答by Vadym Vasyliev
There are a few technical differences. Abstract classes can still do more in comparison to Java 8 interfaces:
有一些技术差异。与 Java 8 接口相比,抽象类仍然可以做更多的事情:
- Abstract class can have a constructor.
- Abstract classes are more structured and can hold a state.
- 抽象类可以有一个构造函数。
- 抽象类更结构化并且可以保存状态。
Conceptually, main purpose of defender methods is a backward compatibility after introduction of new features (as lambda-functions) in Java 8.
从概念上讲,防御者方法的主要目的是在 Java 8 中引入新特性(如 lambda 函数)后向后兼容。
回答by Andrey Chaschev
These two are quite different:
这两个完全不同:
Default methods are to add external functionalityto existing classes without changing their state.
默认方法是向现有类添加外部功能而不改变它们的状态。
And abstract classes are a normal type of inheritance, they are normal classeswhich are intended to be extended.
抽象类是一种普通的继承类型,它们是用于扩展的普通类。
回答by Sufiyan Ghori
As described in thisarticle,
正如在描述这个文章,
Abstract classes versus interfaces in Java 8
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.
引入默认方法后,接口和抽象类似乎是一样的。但是,它们在 Java 8 中仍然是不同的概念。
抽象类可以定义构造函数。它们更加结构化,并且可以具有与之关联的状态。而相比之下,默认方法只能在调用其他接口方法的情况下实现,而不能参考特定实现的状态。因此,两者用于不同目的并在两者之间进行选择实际上取决于场景上下文。
回答by kiriloff
Default methods in Java interface enables interface evolution.
Java 接口中的默认方法支持接口演化。
Given an existing interface, if you wish to add a method to it without breaking the binary compatibility with older versions of the interface, you have two options at hands: add a default or a static method. Indeed, any abstract method added to the interface would have to be impleted by the classes or interfaces implementing this interface.
给定一个现有接口,如果您希望在不破坏与旧版本接口的二进制兼容性的情况下向其添加方法,您有两个选择:添加默认方法或静态方法。实际上,任何添加到接口的抽象方法都必须由实现该接口的类或接口来实现。
A static method is unique to a class. A default method is unique to an instance of the class.
静态方法对于类是唯一的。默认方法对于类的实例是唯一的。
If you add a default method to an existing interface, classes and interfaces which implement this interface do not need to implement it. They can
如果向现有接口添加默认方法,则实现此接口的类和接口不需要实现它。他们能
- implement the default method, and it overrides the implementation in implemented interface.
- re-declare the method (without implementation) which makes it abstract.
- do nothing (then the default method from implemented interface is simply inherited).
- 实现默认方法,并覆盖已实现接口中的实现。
- 重新声明使其抽象的方法(没有实现)。
- 什么都不做(那么来自实现接口的默认方法只是简单地继承)。
More on the topic here.
更多关于这里的主题。
回答by akhil_mittal
Whenever we have a choice between abstract class and interface we should always (almost) prefer default (also known as defender or virtual extensions) methods.
每当我们在抽象类和接口之间做出选择时,我们应该总是(几乎)更喜欢默认(也称为防御者或虚拟扩展)方法。
- Default methods have put an end to classic pattern of interface and a companion class that implements most or all of the methods in that interface. An example is
Collection and AbstractCollection
. Now we should implement the methods in the interface itself to provide default functionality. The classes which implement the interface has choice to override the methods or inherit the default implementation. Another important use of default methods is
interface evolution
. Suppose I had a class Ball as:public class Ball implements Collection { ... }
- 默认方法结束了经典的接口模式和实现该接口中大部分或所有方法的伴随类。一个例子是
Collection and AbstractCollection
。现在我们应该在接口本身中实现方法以提供默认功能。实现接口的类可以选择覆盖方法或继承默认实现。 默认方法的另一个重要用途是
interface evolution
. 假设我有一个 Ball 类:public class Ball implements Collection { ... }
Now in Java 8 a new feature streams in introduced. We can get a stream by using stream
method added to the interface. If stream
were not a default method all the implementations for Collection
interface would have broken as they would not be implementing this new method. Adding a non-default method to an interface is not source-compatible
.
现在在 Java 8 中引入了一个新的特性流。我们可以通过使用stream
添加到接口的方法来获取流。如果stream
不是默认方法,则Collection
接口的所有实现都会中断,因为它们不会实现这个新方法。向接口添加非默认方法不是source-compatible
.
But suppose we do not recompile the class and use an old jar file which contains this class Ball
. The class will load fine without this missing method, instances can be created and it seems everything is working fine. BUTif program invokes stream
method on instance of Ball
we will get AbstractMethodError
. So making method default solved both the problems.
但是假设我们不重新编译该类并使用包含该类的旧 jar 文件Ball
。没有这个缺少的方法,这个类将加载得很好,可以创建实例,看起来一切正常。但是如果程序stream
在实例上调用方法,Ball
我们将得到AbstractMethodError
. 所以使方法默认解决了这两个问题。
回答by Ravindra babu
Regarding your query of
关于您的查询
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 documentation provides perfect answer.
java文档提供了完美的答案。
Abstract Classes Compared to Interfaces:
抽象类与接口的比较:
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.
抽象类类似于接口。您不能实例化它们,它们可能包含声明有或没有实现的混合方法。
但是,使用抽象类,您可以声明非静态和最终的字段,并定义公共、受保护和私有的具体方法。
对于接口,所有字段都自动是 public、static 和 final,并且您声明或定义的所有方法(作为默认方法)都是 public。此外,您只能扩展一个类,无论它是否是抽象的,而您可以实现任意数量的接口。
Use cases for each of them have been explained in below SE post:
下面的 SE 帖子中解释了它们中的每一个的用例:
What is the difference between an interface and abstract class?
Are the abstract classes still useful in that scenario?
抽象类在那种情况下仍然有用吗?
Yes. They are still useful. They can contain non-static, non-final methodsand attributes (protected, private in addition to public), which is not possible even with Java-8 interfaces.
是的。它们仍然有用。它们可以包含非静态的、非最终的方法和属性(除了 public 之外,protected、private),这即使使用 Java-8 接口也是不可能的。
回答by Ahmad Sanie
when should interface with default methods be used and when should an abstract class be used?
什么时候应该使用带有默认方法的接口,什么时候应该使用抽象类?
Backward compatibility:Imagine that your interface is implemented by hundreds of classes, modifying that interface will force all the users to implement the newly added method, even though it could be not essential for many other classes that implements your interface, Plus it allows your interface to be a functional interface
向后兼容性:假设您的接口由数百个类实现,修改该接口将强制所有用户实现新添加的方法,即使对于实现您的接口的许多其他类可能不是必需的,而且它允许您的接口成为一个功能接口
Facts & Restrictions:
事实与限制:
1-May only be declared within an interface and not within a class or abstract class.
1-只能在接口中声明,不能在类或抽象类中声明。
2-Must provide a body
2-必须提供身体
3-It is not assumed to be abstract as other normal methods used in an interface.
3-它不像接口中使用的其他普通方法那样被假定为抽象的。
回答by Nicolas Zozol
Remi Foraxrule is You don't design with Abstract classes. You design your app with interfaces. Watever is the version of Java, whatever is the language. It is backed by the Interface segregation principlein SOLIDprinciples.
Remi Forax规则是您不要使用抽象类进行设计。你用接口设计你的应用程序。Watever 是 Java 的版本,无论是什么语言。它是由支持我覆盖整个院落隔离原则在SOL我d的原则。
You can later use Abstract classes to factorize code. Now with Java 8 you can do it directly in the interface. This is a facility, not more.
您可以稍后使用抽象类来分解代码。现在使用 Java 8,您可以直接在界面中执行此操作。这是一个设施,而不是更多。