请考虑以下代码段:
class Test1 {
private static Test1 instance;
@NonNull private final Date date1;
@NonNull private final Date date2;
Test1() throws Exception {
this.date1 = new Date();
Test1.instance = this;
if (true) {
throw new Exception();
}
this.date2 = new Date();
}
public void dump() {
System.out.println("date1: " + date1);
System.out.println("date2: " + date2);
}
static void test() {
Test1 t1 = null;
try {
t1 = new Test1();
} catch (Exception e) {
e.printStackTrace();
}
Test1.instance.dump();
assert t1 == null;
}
}
Test1的构造函数在将自身分配给静态字段后总是抛出异常.该字段保留对部分初始化对象的引用:date2字段为null的对象,即使它声明为@NonNull和final.
test()函数不能直接获取对生成的t1的引用.在catch块之后,t1为null.
然而,Test1.instance很好,调用它的dump()函数显示date1已初始化但date2为null.
这里发生了什么?为什么我可以保持对真正处于非法状态的对象的引用?