抽象类通过“向上收、向下稳”统一管理共性字段与初始化逻辑:共性字段直接定义在抽象类中并设默认值;构造逻辑由抽象类带参构造器封装,子类通过super()复用;无参通用初始化用构造代码块自动执行;禁止在构造期调用抽象方法,应延后至业务方法或显式init()调用。

抽象类抽取公共属性与初始化逻辑,核心是“向上收、向下稳”:把多个子类重复声明的字段和固定初始化动作统一提到抽象父类里,既减少冗余,又确保每次创建子类实例时这些基础状态都被可靠设置。
共性字段直接定义在抽象类中
多个子类都声明了 id、createdAt、status、createUser 等字段?别各自写一遍。直接在抽象类里用 protected 修饰统一定义:
- protected String id;
- protected LocalDateTime createdAt = LocalDateTime.now();
- protected Integer status = Status.ACTIVE.getValue();
这样所有子类自动继承,不用再重复声明,也不用担心某个子类漏写或写错默认值。
构造逻辑交给抽象类的构造器
子类需要传参初始化共性字段(比如 id 或 createUser),就在抽象类里提供带参构造函数:
立即学习“Java免费学习笔记(深入)”;
- protected BaseEntity(String id, Integer createUser) { this.id = id; this.createUser = createUser; this.createdAt = LocalDateTime.now(); }
- 子类构造器第一行写 super(id, user),复用初始化逻辑
- 如果子类有自己专属字段(如 userName、email),再在 super() 后单独赋值
避免每个子类都手动 new 字段、设默认值、调 init 方法——统一入口,一次写对,处处安全。
用构造代码块补足无参通用初始化
有些初始化不依赖参数,比如集合字段、标志位、日志记录,适合用实例初始化块(构造代码块):
- { tags = new ArrayList(); }
- { version = 1; isActive = true; }
- { System.out.println("BaseEntity initialized"); }
它会在每个构造器执行前自动运行,不管子类调用哪个重载构造器,这些逻辑都自动生效,无需显式调用,也不怕遗漏。
避免在构造期调用抽象方法
抽象类里如果定义了 abstract 方法,千万别在构造器或构造代码块里直接调用它:
- 子类字段还没初始化,此时调用 abstract loadData() 可能返回 null 或 0
- 正确做法:把需子类定制的行为延后到业务方法中(比如 create()、load()),不在构造阶段触发
- 若必须提前准备数据,改用 protected init() 方法,由子类在 super() 后显式调用
构造阶段只做确定性初始化,不确定的部分留给后续明确调用,更可控也更安全。


















