Java中抽象类和接口的区别
抽象类和接口之间的区别是常见的面试问题之一。抽象类和接口是 Java 编程语言的核心部分。选择接口还是抽象类是每个架构师面临的设计决策。在我上一篇文章中,我提供了尽可能多的有关Java 接口和抽象类的详细信息。在这篇文章中,我们将了解抽象类和接口之间的区别,以及何时应该使用接口而不是抽象类,反之亦然。
抽象类和接口之间的区别
abstract
关键字用于创建抽象类,并且也可以与方法一起使用,而interface
关键字用于创建接口,但不能与方法一起使用。- 子类使用
extends
关键字来扩展抽象类,并且它们需要提供抽象类中所有声明的方法的实现,除非子类也是抽象类,而子类使用implements
关键字来实现接口,并且应该为接口中声明的所有方法提供实现。 - 抽象类可以具有带实现的方法,而接口提供绝对抽象,不能具有任何方法实现。请注意,从 Java 8 开始,我们可以在包含方法实现的接口中创建默认方法和静态方法。
- 抽象类可以有构造函数,但接口不能有构造函数。
- 抽象类具有普通 Java 类的所有功能,只是我们无法实例化它。我们可以使用
abstract
关键字使类抽象化,但接口是完全不同的类型,只能具有公共静态最终常量和方法声明。 - 抽象类方法可以具有公共、私有、受保护、静态等访问修饰符,但接口方法隐式地是公共和抽象的,我们不能对接口方法使用任何其他访问修饰符。
- 一个子类只能扩展一个抽象类,但可以实现多个接口。
- 抽象类可以扩展其他类并实现接口,但接口只能扩展其他接口。
- 如果抽象类具有
main()
方法,我们可以运行它,但我们不能运行接口,因为它们不能有主要方法的实现。 - 接口用于定义子类的契约,而抽象类也定义契约,但它可以提供其他方法的实现供子类使用。
这就是接口和抽象类之间的区别,现在我们可以继续了解何时应该使用接口而不是抽象类,反之亦然。
接口或抽象类
Whether to choose between Interface or abstract class for providing a contract for subclasses is a design decision and depends on many factors. Let’s see when Interfaces are the best choice and when can we use abstract classes.
- Java doesn’t support multiple class level inheritance, so every class can extend only one superclass. But a class can implement multiple interfaces. So most of the times Interfaces are a good choice for providing the base for class hierarchy and contract. Also coding in terms of interfaces is one of the best practices for coding in java.
- If there are a lot of methods in the contract, then abstract class is more useful because we can provide a default implementation for some of the methods that are common for all the subclasses. Also if subclasses don’t need to implement a particular method, they can avoid providing the implementation but in case of interface, the subclass will have to provide the implementation for all the methods even though it’s of no use and implementation is just empty block.
- If our base contract keeps on changing then interfaces can cause issues because we can’t declare additional methods to the interface without changing all the implementation classes, with the abstract class we can provide the default implementation and only change the implementation classes that are actually going to use the new methods.
Use Abstract classes and Interface both
Using interfaces and abstract classes together is the best approach to design a system. For example, in JDK java.util.List
is an interface that contains a lot of methods, so there is an abstract class java.util.AbstractList
that provides a skeletal implementation for all the methods of List interface so that any subclass can extend this class and implement only required methods. We should always start with an interface as the base and define methods that every subclass should implement and then if there are some methods that only certain subclass should implement, we can extend the base interface and create a new interface with those methods. The subclasses will have the option to chose between the base interface or the child interface to implement according to its requirements. If the number of methods grows a lot, it’s not a bad idea to provide a skeletal abstract class implementing the child interface and providing flexibility to the subclasses to chose between interface and an abstract class.
Java 8 interface changes
From Java 8 onwards, we can have method implementations in the interfaces. We can create default as well as static methods in the interfaces and provide an implementation for them. This has bridged the gap between abstract classes and interfaces and now interfaces are the way to go because we can extend it further by providing default implementations for new methods. For more details, check out Java 8 interface default static methods.