该用接口还是抽象类取决于设计意图:定义行为契约用接口,描述本质并复用代码用抽象类;接口支持多实现但无状态,抽象类支持单继承、构造器和实例状态。

接口和抽象类到底该用哪个?看设计意图先
选接口还是抽象类,不是语法问题,而是设计问题:如果你在定义「一类对象该有什么行为」,比如 Flyable、Serializable,就用接口;如果你在描述「一类对象是什么」并想复用代码,比如 Animal(有名字、年龄、通用的 sleep() 方法),就用抽象类。
常见错误是:为了一堆类都有 id 和 createdAt 字段,硬写个抽象类,结果发现这些类根本没继承关系——这时该用接口 + 默认方法,或干脆用组合(如引入 BaseEntity 类作为字段)。
方法实现和修饰符差异直接影响可维护性
抽象类里的方法可以是 protected、private,甚至构造器里做初始化;接口里的所有方法默认是 public abstract,连 protected 都不许写(编译直接报错)。Java 8+ 虽支持 default 和 static 方法,但它们不能访问实例状态——也就是说,default 方法没法调用 this.name。
- 需要共享逻辑且依赖子类字段?→ 抽象类
- 想给多个不相关类加统一工具方法(如
validate())?→ 接口 +default - 误在接口里写
private void helper() { }?→ 编译失败,Java 不允许
多实现 vs 单继承:架构灵活性的底层约束
一个类只能 extends 一个抽象类,但能 implements 任意多个接口。这是 Java 的硬限制,不是风格选择。
立即学习“Java免费学习笔记(深入)”;
典型踩坑场景:
- 你写了
abstract class Vehicle,又想让Drone同时具备Vehicle和Flyable行为 → 只能靠Vehicle去implements Flyable,再让Drone extends Vehicle;不能让Drone既extends Vehicle又extends FlyingObject - 接口之间可以
extends多个,比如interface SmartDevice extends Connectable, Upgradable, Loggable—— 这是安全的,也是推荐的分层契约方式
字段和构造器:别在接口里存状态
接口里声明的变量自动变成 public static final,哪怕你只写 int MAX_RETRY = 3;,它也等价于 public static final int MAX_RETRY = 3;。而抽象类可以有 private String name;、protected List<string> tags;</string>,还能在构造器里赋初值。
容易忽略的一点:abstract class 的构造器不会被子类继承,但子类构造时会隐式/显式调用它——这意味着你可以在抽象类构造器中做校验(如 if (name == null) throw new IllegalArgumentException();),而接口完全做不到这点。
如果看到有人在接口里定义 String VERSION = "1.0" 并期望它被子类“继承”为实例字段,那已经混淆了常量和状态的概念。








