2025.5.27
Interface(接口) vs Abstract Class(抽象类)对比
在面向对象编程(OOP)中,接口(Interface)和抽象类(Abstract Class)都是用于实现多态和代码抽象的机制,但它们在设计目的和使用场景上有显著区别。以下是详细对比:
1. 核心区别
| 特性 | 接口(Interface) | 抽象类(Abstract Class) |
|---|---|---|
| 定义 | 纯抽象契约,仅声明方法(无实现)。 | 可包含抽象方法(无实现)和具体方法(有实现)。 |
| 多继承 | 一个类可实现多个接口(implements A, B)。 |
一个类只能继承一个抽象类(extends)。 |
| 成员变量 | 只能是 public static final(常量)。 |
可以是任意类型(实例变量、静态变量等)。 |
| 方法修饰符 | 默认 public abstract(Java 8+支持default方法)。 |
可包含 abstract、非抽象方法,甚至private方法。 |
| 构造方法 | 不能有构造方法。 | 可以有构造方法(用于子类初始化)。 |
| 设计目的 | 定义“能做什么”(行为契约)。 | 定义“是什么”(部分共性的抽象实现)。 |
2. 使用场景
何时用接口?
- 需要定义跨继承树的行为契约(例如:
Serializable、Comparable)。 - 需要实现多重继承(一个类实现多个接口)。
- 强调“has-a”关系(如:
Bird implements Flyable)。
何时用抽象类?
- 需要复用部分代码逻辑(抽象类可提供具体方法)。
- 子类之间有明显的“is-a”继承关系(如:
Dog extends Animal)。 - 需要控制子类的初始化过程(通过构造方法)。
3. 代码示例
接口(Interface)
interface Flyable {
void fly(); // 默认是 public abstract
default void land() { // Java 8+ 的默认方法
System.out.println("Landing...");
}
}
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying");
}
}
抽象类(Abstract Class)
abstract class Animal {
private String name;
public Animal(String name) { // 构造方法
this.name = name;
}
abstract void makeSound(); // 抽象方法
public void eat() { // 具体方法
System.out.println(name + " is eating");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类构造方法
}
@Override
void makeSound() {
System.out.println("Woof!");
}
}
4. Java 8+ 对接口的增强
- 默认方法(Default Methods):
允许接口提供默认实现,避免破坏现有代码(如Collection.stream())。 - 静态方法(Static Methods):
接口可以定义静态工具方法(如Comparator.comparing())。
5. 总结
| 选择依据 | 接口 | 抽象类 |
|---|---|---|
| 需要多重继承? | ✅ 是 | ❌ 否 |
| 需要共享代码实现? | ❌ 否(Java 8后可通过default方法部分实现) |
✅ 是 |
| 需要定义常量? | ✅ 是(public static final) |
✅ 是(任意变量) |
| 需要构造方法? | ❌ 否 | ✅ 是 |
经验法则:
- 优先使用接口:定义行为契约(如
Runnable、Comparable)。 - 使用抽象类:当多个子类有共享逻辑时(如模板方法模式)。

浙公网安备 33010602011771号