接口与抽象类:契约还是模板
更新时间:2026-09-20。两者都用来定义「抽象」,但设计意图不同:接口是能力契约(can-do),抽象类是同类模板(is-a)。理解多态机制后再看本篇更顺,见继承与多态。
一、核心区别对照表
| 维度 | 接口 interface | 抽象类 abstract class |
|---|---|---|
| 语义 | 「能做什么」的契约 | 「是什么」的半成品模板 |
| 继承/实现 | 一个类可 implements 多个 | 只能 extends 一个 |
| 构造器 | 没有 | 有(供子类 super 调用) |
| 字段 | 隐式 public static final 常量 | 可有普通实例字段、各种状态 |
| 方法 | 抽象方法;Java 8+ 可 default/static;Java 9+ 可 private | 抽象方法 + 任意具体方法 |
| 访问控制 | 方法默认 public | 任意修饰符 |
| 适用 | 定义跨类型的统一行为 | 多个相关类共享代码/状态 |
二、接口:定义能力
java
interface Payable { // 能力契约:能支付
boolean pay(long cents); // 隐式 public abstract
static Payable alipay() { return new AlipayPay(); } // 静态工厂
default void refund(long cents) { // default:给实现类一个默认实现
throw new UnsupportedOperationException();
}
}
class OrderService implements Payable, Serializable { // 可实现多个接口
@Override public boolean pay(long cents) { /* ... */ return true; }
}default 方法解决了「接口加方法会让所有实现类编译失败」的演进难题,但也带来多接口同名 default 冲突:实现类必须重写消歧(Payable.super.refund(n))。
三、抽象类:提炼模板
java
abstract class AbstractRepository {
protected final String table; // 可有状态
AbstractRepository(String table) { this.table = table; } // 有构造器
abstract Object doQuery(String sql); // 留给子类实现
public final Object findById(long id) { // 固定流程(模板方法)
return doQuery("select * from " + table + " where id=" + id);
}
}
class UserRepository extends AbstractRepository {
UserRepository() { super("t_user"); }
@Override Object doQuery(String sql) { /* JDBC ... */ return null; }
}抽象类不能 new,但可以有 main、构造器;抽象方法所在类必须声明为 abstract。

四、选型规则
- 优先接口:定义不相关类也可能共享的行为(
Comparable、Runnable、Closeable),需要多实现或让类型灵活演化。 - 用抽象类:一组强相关类要共享字段/构造/公共代码,或需要 protected 方法、非 final 状态,典型是模板方法模式固定骨架。
- 组合拳:接口定契约,抽象类做「骨架实现」(如
List接口 +AbstractList+ArrayList),使用者二选一即可。
坑
- 接口字段误以为是实例字段:接口里的变量全是
public static final常量,不能存对象状态。 - default 方法菱形冲突:两个接口有同名同参 default 时,类必须重写,否则编译报错。
- 抽象类滥用导致继承层级僵化:Java 单继承,一旦占了 extends 位就无法再继承别的;能 implements 就别轻易占用 extends。
- 抽象方法可见性:接口抽象方法默认 public,实现时不能收窄成 protected/private。
- 把工具常量堆进接口(常量接口反模式):实现类会平白暴露这些常量,应改用
enum或final class + static import。
总结
接口是「能做什么」的纯契约,支持多实现、字段全为常量,Java 8 起用 default 方法平滑演进;抽象类是「是什么」的半成品,提供构造器、实例字段与公共方法但只能单继承。选型上跨类型的统一能力优先定义成接口,强相关类共享状态与固定流程用抽象类做模板,大型框架常让抽象骨架类实现接口,兼顾灵活与复用。 多态与重写规则见继承与多态。