Java成员变量初始化阶段为何可以使用this关键字?
关于AbstractApplicationContext字段初始化中this关键字的解答
你看到的Spring源码片段如下:
private String id = ObjectUtils.identityToString(this);
这里的核心问题是对Java对象初始化的时序认知有偏差,这个阶段使用this是完全合法的,不存在语法问题:
- 先理清楚Java创建对象的完整执行顺序:
- 执行new指令时,JVM首先会在堆内存为目标对象分配固定的内存空间,之后把对象所有实例字段先设为对应类型的默认值——引用类型默认是null,int这类基础类型默认是0,boolean默认是false。这一步走完,对象的内存地址就已经确定了,
this本质就是指向这块内存的引用,此时已经是合法可用的状态,这个节点远早于我们常说的「对象实例化完成」。 - 内存分配、默认值赋值完成后,JVM才会按继承层级从上到下执行:父类的实例字段初始化逻辑、父类构造方法,之后才轮到当前类的实例字段赋值表达式(也就是你看到的这行id赋值代码),最后执行当前类的构造方法体。只有构造方法全部执行完毕,才算对象完全初始化完成,可以对外正常使用。
- 执行new指令时,JVM首先会在堆内存为目标对象分配固定的内存空间,之后把对象所有实例字段先设为对应类型的默认值——引用类型默认是null,int这类基础类型默认是0,boolean默认是false。这一步走完,对象的内存地址就已经确定了,
- 再看
ObjectUtils.identityToString(this)的逻辑:这个方法只会读取传入对象的身份哈希值(和对象内存地址绑定的原生哈希),拼接成唯一标识字符串,全程不会访问对象的其他实例字段,也不会调用对象的业务方法,只需要拿到合法的对象引用就能正常执行,根本不要求对象完成全部初始化。 - 平时我们说「实例化没完成不能用this」,本质是警告不要在构造阶段把
this泄露给外部代码:如果外部代码拿到半初始化的对象,去访问还没赋值的字段、调用依赖初始化状态的方法,很容易触发空指针或者逻辑错误,不是说这个阶段this引用本身不存在、不能在类内部传递。
Spring这里的写法完全符合Java语法规范,没有问题。
内容的提问来源于stack exchange,提问作者17u
相关产品推荐
相关产品推荐

