Java 接口 vs 抽象类:如何选择合适的抽象方式
什么是接口?
在 Java 中,接口定义类可实现的契约。接口中声明的所有方法默认是抽象的,即无方法体。接口不能直接实例化;它们仅描述行为。
接口不能持有实例变量,但可用 public static final 修饰符声明常量。
什么是抽象类?
抽象类是不能实例化的类,可同时包含抽象方法(无方法体)和具体方法(有实现)。至少需要一个抽象方法。
抽象类作为子类蓝图,子类必须实现父类定义的任何抽象方法。
与接口不同,抽象类可通过实例字段维护状态并提供默认行为。
为什么使用接口?
- 封装行为而不绑定特定实现。
- 启用运行时动态分派和多态。
- 通过将方法签名与继承层次分离促进松耦合。
- 允许类实现多个接口,提供灵活设计。
为什么使用抽象类?
- 提供可被子类复用的共享代码。
- 为相关类提供模板同时强制通用行为。
- 通过实例字段支持有状态行为。
- 通过限制单一父类实现受控继承。
接口 vs 抽象类
两种抽象都帮助定义契约,但在实现和用法上不同。接口只能声明方法,抽象类可提供默认实现。类只能扩展一个抽象类但可实现多个接口。
| 方面 | 接口 | 抽象类 |
|---|---|---|
| 查找速度 | 通常较慢,因动态分派 | 可能时静态分派较快 |
| 多重继承 | 支持实现多个接口 | 仅单继承 |
| 方法体 | 仅抽象(Java 8 前)或 default/static(Java 8+) | 可同时包含抽象和具体方法 |
| 状态 | 不能声明实例字段 | 可声明实例字段和构造器 |
| 用例 | 定义可混入无关类的能力 | 提供带共享实现的公共基类 |
| 成员可见性 | 所有成员隐式 public | 成员可为 protected、public 或 private |
| 扩展其他类型 | 可扩展其他接口 | 可扩展类并实现接口 |
| 构造器 | 不能定义构造器 | 可为子类定义构造器 |
| 常量 | 可定义常量(public static final) | 可定义常量和普通字段 |
示例代码:Java 接口与抽象类
下面简例演示如何声明和使用接口及抽象类。
接口语法
interface Name {
// 方法声明
}
Java 接口示例
interface Pet {
void test();
}
class Dog implements Pet {
public void test() {
System.out.println("Interface method implemented");
}
public static void main(String[] args) {
Pet p = new Dog();
p.test();
}
}
抽象类语法
abstract class Name {
// 代码
}
抽象类示例
abstract class Shape {
int b = 20;
abstract void calculateArea();
}
class Rectangle extends Shape {
public static void main(String[] args) {
Rectangle obj = new Rectangle();
obj.b = 200;
obj.calculateArea();
}
void calculateArea() {
System.out.println("Area is " + (b * b));
}
}
java