父类构造器中禁止使用子类的this,因其会导致字段未初始化、方法未就绪而引发空指针或状态错乱;应将逻辑移至init()、start()等显式初始化方法,或采用static工厂方法+私有构造器确保安全发布。

父类构造器中直接使用子类的 this,本质上是在对象“还没长成型”时就把它推上岗位——此时子类字段为空、方法未就绪,极易引发空指针或状态错乱。关键不是“能不能用”,而是“该不该在那个时间点暴露它”。
父类构造器里别碰子类可重写的方法
父类构造器执行时,子类构造器尚未开始,所有被子类覆写的方法(哪怕只是简单 getter)都可能访问到未初始化的字段。
- 避免在父类构造器中调用 非 private / 非 final 的实例方法
- 把逻辑移到
init()或工厂方法中,确保子类字段已赋值后再触发 - 若必须在构造阶段做某些事,改用 static 工厂方法 + 私有构造器,控制初始化顺序
监听注册、线程启动等操作一律后移
父类构造器里调用 register(this) 或 new Thread(this::run).start(),等于把半成品交出去——子类字段可能还是默认值(null、0、false)。
- 监听注册、事件绑定、资源启动等,统一放到 显式初始化方法 中(如
start()、open()) - 确保该方法只在对象完全构造完毕、且由单线程调用后执行
- 必要时配合
volatile或安全发布机制(如AtomicReference.setRelease())防止重排序
警惕内部类和匿名类隐式持有 this
父类构造器中定义匿名内部类或非静态成员内部类,编译器会自动注入 this$0 引用——而此时子类部分根本没初始化。
- 禁止在父类构造器中创建 非静态内部类,尤其当它会被外部持有或异步调用时
- 改用 静态内部类 + 显式传参,切断对外部实例的隐式依赖
- 若需回调,用函数式接口(如
Runnable)并延迟传递,而非直接捕获this
final 字段不等于绝对安全
即使子类字段声明为 final,只要 this 在构造完成前逃逸,其他线程仍可能看到其默认值(JVM 不保证逃逸场景下的初始化可见性)。
-
final字段必须在构造器中 直接赋值,且不能依赖虚方法调用 - 避免在构造器中将
this传给任何可能跨线程使用的组件(如全局集合、事件总线、线程池) - 对必须早期注册的监听器,考虑用 弱引用 或生命周期感知设计(如仅在
start()后激活)

















