Java中向private final成员传递this是否属于不良实践?
初始化private final成员时传递this属于不良实践吗?
这种做法绝对属于不良实践,核心问题是你把未完全构造的Book对象引用(this)提前传给了Chapter的构造器,导致其他对象看到了处于不一致状态的Book实例。
你的代码里的具体问题
Java中实例对象的初始化顺序是固定的:先执行所有实例变量的初始化语句,再执行构造器内部的代码。在你给出的代码里:
chapter1和chapter2的初始化会先于Book构造器执行,此时title只是被声明了,还没在构造器里赋值,所以Chapter构造器里拿到的book.title是null。- 哪怕
title是final修饰的,只要它是在构造器里赋值(而非声明时直接初始化),在实例变量初始化阶段它的值就是默认初始值(String类型就是null)。
为什么这是危险的
传递未完全构造的对象引用,会让依赖该对象的其他组件(比如这里的Chapter)看到对象的不完整状态:
- 如果后续
Chapter的逻辑需要用到book.title,就会因为拿到null触发空指针异常或者业务逻辑错误。 - 哪怕是单线程场景,这种状态不一致也会增加代码的理解难度和维护成本;如果是多线程环境,还可能引发更复杂的线程安全问题——其他线程可能看到
Book对象的部分字段已初始化、部分未初始化的混乱状态。
怎么修复
有两种常见的修复方式:
- 把Chapter的初始化移到构造器里
等title赋值完成后,再创建Chapter实例,确保this传递的是完全构造好的Book对象:
public class Book { protected final String title; private final Chapter chapter1; private final Chapter chapter2; private class Chapter { private final Book book; Chapter(Book b) { book = b; // 此时title已经完成赋值 } } Book() { title = "Book: 2 Chapters"; chapter1 = new Chapter(this); chapter2 = new Chapter(this); } }
- 直接在声明时初始化title
如果title的值可以提前确定,直接在声明时赋值,这样实例变量初始化阶段title就已有值,传递this给Chapter时不会出现null:
public class Book { protected final String title = "Book: 2 Chapters"; private class Chapter { private final Book book; Chapter(Book b) { book = b; // 此时title已经初始化完成 } } private final Chapter chapter1 = new Chapter(this); private final Chapter chapter2 = new Chapter(this); Book() { // 无需再给title赋值 } }
内容的提问来源于stack exchange,提问作者pmoubed
相关产品推荐
相关产品推荐

