编程Java开发人员

描述Java中抽象类和接口的关键区别,以及在何种情况下应使用它们。

用 Hintsage AI 助手通过面试

答复

抽象类可以包含抽象方法和具体方法(带实现),以及状态(数据字段)。一个类只能继承一个抽象类。当需要为继承层次结构概括某些逻辑和状态时,使用抽象类。

接口仅定义方法的签名(在Java 8之前),从Java 8开始可以包含默认实现(default)的方法和静态方法,但没有状态。一个类可以实现多个接口。使用接口定义与继承层次结构无关的行为集。

示例:

abstract class Animal { String name; public Animal(String name) { this.name = name; } abstract void makeSound(); } interface Movable { void move(); } class Dog extends Animal implements Movable { public Dog(String name) { super(name); } void makeSound() { System.out.println("Woof!"); } public void move() { System.out.println("Runs"); } }

误导性问题

仅包含抽象方法的抽象类与Java 8之前的接口有什么区别?它们可以互换使用吗?

回答: 不,不能总是。接口不能包含状态(实例字段),并且支持多重实现,而抽象类的继承是单一的。此外,接口的方法签名始终是public。


由于对这一主题细节的不了解而导致的实际错误示例


故事

在一个项目中,需要实现多个行为相似但属于不同层次的对象接口。开发人员选择使用抽象类,从而无法使用多重继承。最后导致了重大重构和代码重复。


故事

在一个大型REST API项目中创建了一个带字段(常量)的接口,以为这些值是可变的,就像在普通类中一样。结果试图修改这些字段导致了静默失败——值保持不变,错误长时间未被发现。


故事

在迁移到Java 8的过程中,开发人员在接口中添加了带实现的方法,但忘记考虑到部分类还通过抽象类继承同名方法。这导致了方法冲突和在解析继承时产生意外结果。