抽象类通过构造方法初始化公共属性最可靠,需用super()调用并校验参数;final字段强制子类传参赋值;默认值、共享依赖在构造中初始化;通用逻辑用实例初始化块;禁止在构造中调用抽象方法。

抽象类不能直接实例化,但它的构造方法会在子类创建对象时自动执行(通过 super() 调用),这是初始化公共属性最可靠、最规范的入口。
用带参构造强制传入必需字段
把所有子类共用且不可缺失的属性声明为 final,并在抽象类构造方法中一次性赋值。这样既防止子类遗漏,也避免后续被意外修改:
- 比如
protected final String code;和protected final LocalDateTime createdAt; - 构造方法里校验参数合法性(如非 null、格式正确、范围合理),再赋值
- 子类必须显式调用
super(code, now),否则编译不通过
在构造方法中设默认值或初始化共享依赖
对有合理默认行为的字段(如状态、重试次数、日志器),直接在构造方法中初始化,而不是靠声明时赋值或子类自行处理:
this.status = Status.PENDING;this.retryLimit = 3;-
this.logger = LoggerFactory.getLogger(getClass());—— 注意用getClass()可获取真实子类名
配合构造代码块补足无参通用逻辑
有些初始化不依赖构造参数(如新建集合、设置标志位、打印调试日志),适合用实例初始化块({ ... }):
{ tags = new ArrayList(); }{ isActive = true; version = 1; }- 它在每个构造方法执行前自动运行,无论子类调用哪个重载构造器,逻辑都不会遗漏
避开常见陷阱:别在构造阶段调用抽象方法
抽象类构造方法或代码块里,绝对不要直接调用 abstract 方法:
- 此时子类字段尚未初始化,可能导致空指针或返回默认值(0、null)
- 正确做法是把定制逻辑延后到业务方法中(如
init()、load()),由子类在super()后主动触发 - 若必须提前准备,可定义 protected init(),并明确要求子类在构造末尾调用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











