Java 中接口与抽象类的比较与选择
✅ 一、共同点
-
都不能直接实例化
不能使用new
创建对象,只能被继承(extends)或实现(implements)。 -
都可以定义抽象方法
都可以规定子类/实现类必须实现的方法,实现“规范”。 -
都支持多态性
可以用接口或抽象类的引用指向子类对象,实现面向接口编程。
❗二、区别对比
特性 | 接口(Interface) | 抽象类(Abstract Class) |
---|---|---|
关键字 | interface | abstract class |
方法类型 | 只能有抽象方法(JDK8+ 可有默认实现) | 可以有抽象方法和具体方法 |
成员变量 | 只能是 public static final 常量 | 可以有各种修饰符的变量(实例变量、常量等) |
构造函数 | ❌ 不允许有构造方法 | ✅ 可以有构造方法 |
多继承 | ✅ 可以实现多个接口(多实现) | ❌ 只能单继承 |
适合场景 | 行为规范,强调“能做什么” | 基类抽象,共享代码、状态 |
默认方法(JDK8+) | default 方法支持 | 支持具体方法 |
静态方法(JDK8+) | 支持 static 方法 | 也支持 static 方法 |
三、如何选择?
✅ 用接口的场景:
- 更像是一种能力或行为的规范,如:
Comparable
、Runnable
、Serializable
- 需要多继承:类已经有父类,但还需要其他功能(接口)
- 希望调用方只依赖接口而不是具体实现(面向接口编程)
推荐:开发中优先接口,用组合代替继承。
✅ 用抽象类的场景:
- 有一组子类共享部分代码(逻辑、状态等)
- 有默认行为,子类可选择复用或重写
- 只希望被一组子类继承(例如模板方法模式)
举个例子
// 接口:行为规范(例如:所有动物都会叫)
interface Animal {
void makeSound(); // 只定义行为
}
// 抽象类:提供基础实现
abstract class Bird {
public void layEggs() {
System.out.println("Laying eggs...");
}
public abstract void fly(); // 强制子类实现
}
总结口诀
“抽象类写模板,接口定行为;如果只能选一个,那就优先接口。”