抽象类和接口的区别是一个常见的面试问题。抽象类和接口是Java编程语言的核心部分。选择使用接口还是抽象类是每个架构师都会面临的设计决策。在我的最新文章中,我尽可能详细地介绍了Java接口和抽象类。在这篇文章中,我们将了解抽象类和接口之间的区别,以及何时应该使用接口而非抽象类,反之亦然。
抽象类和接口的区别
abstract
关键字用于创建抽象类,它还可以与方法一起使用,而interface
关键字用于创建接口,但不能与方法一起使用。- 子类使用
extends
关键字扩展抽象类,它们需要提供抽象类中所有已声明方法的实现,除非子类也是抽象类,而子类使用implements
关键字实现接口,并应为接口中声明的所有方法提供实现。 - 抽象类可以拥有带有实现的方法,而接口提供绝对抽象,不能有任何方法的实现。请注意,从Java 8开始,我们可以在接口中创建默认和静态方法,这些方法包含了方法的实现。
- 抽象类可以有构造函数,而接口不能有构造函数。
- 抽象类具有普通Java类的所有特性,只是我们不能实例化它。我们可以使用
abstract
关键字使类成为抽象类,但接口是一种完全不同的类型,只能具有public static final常量和方法声明。 - 抽象类的方法可以具有public、private、protected、static等访问修饰符,但接口方法默认为public和abstract,我们不能在接口方法中使用其他访问修饰符。
- A subclass can extend only one abstract class but it can implement multiple interfaces.
- 抽象类可以扩展其他类并实现接口,而接口只能扩展其他接口。
- 如果抽象类有
main()
方法,我们可以运行它,但我们无法运行接口,因为它们不能有主方法的实现。 - 接口用于为子类定义合同,而抽象类也定义合同,但它可以为子类提供其他方法的实现。
这就是关于接口和抽象类之间的区别的全部内容,现在我们可以继续了解何时应该使用接口而不是抽象类,反之亦然。
接口或抽象类
选择接口还是抽象类作为子类的合同提供是一个设计决策,取决于许多因素。让我们看看接口何时是最佳选择,以及何时可以使用抽象类。
- Java不支持多类级继承,因此每个类只能扩展一个超类。但一个类可以实现多个接口。因此,大多数情况下,接口是提供类层次结构和合同基础的良好选择。此外,在Java编码中,按照接口进行编码是最佳实践之一。
- 如果合同中有很多方法,那么抽象类更有用,因为我们可以为一些对所有子类都通用的方法提供默认实现。此外,如果子类不需要实现特定方法,它们可以避免提供实现,但在接口的情况下,子类将不得不为所有方法提供实现,即使它没有用处且实现为空块。
- 如果我们的基础合同不断变化,那么接口可能会引起问题,因为我们不能在不更改所有实现类的情况下向接口添加附加方法;而使用抽象类,我们可以提供默认实现,只需更改实际将使用新方法的实现类。
使用抽象类和接口
同时使用接口和抽象类是设计系统的最佳方法。例如,在JDK中,java.util.List
是一个包含许多方法的接口,因此有一个抽象类java.util.AbstractList
,它为List接口的所有方法提供了骨架实现,以便任何子类可以扩展此类并仅实现所需的方法。我们应始终以接口为基础,并定义每个子类应实现的方法。如果有一些方法只有某些子类应实现,我们可以扩展基础接口,并创建一个新接口,其中包含这些方法。子类将有选择地在基础接口或子接口之间进行选择,根据其需求进行实现。如果方法数量增多,为子接口提供一个骨架抽象类并提供灵活性,使子类可以在接口和抽象类之间进行选择。
Java 8接口变更
从Java 8开始,我们可以在接口中拥有方法实现。我们可以在接口中创建默认方法和静态方法,并为它们提供实现。这弥补了抽象类和接口之间的差距,现在接口是首选的方式,因为我们可以通过为新方法提供默认实现来进一步扩展它。有关更多详细信息,请查看Java 8接口默认静态方法。