はこのスニペットを考えてみましょう:Java:コンストラクタが失敗したオブジェクトはどうなりますか?
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
になります。
ここでは何が起こっていますか?なぜ本当に違法な状態にあるオブジェクトへの参照を保持できますか? t1
がnullであるという事実は、(In Java what happens when an object fails to be instantiated?とは違って)明らかにされていることを
EDIT 。この質問は、静的フィールドに格納されたオブジェクトの状態に関するものです。
インスタンスを作成して初期化するのは別の作業です。インスタンスが最初に作成された後、そのインスタンスがコンストラクタによって初期化されます。オブジェクトが完全に初期化されていなくても、インスタンスはまだ存在します。これは* unsafe publication *の例です。あなたは(明らかに)それを避けるべきです。 –
[Javaではオブジェクトのインスタンス化に失敗した場合どうしますか?](http://stackoverflow.com/questions/3421606/in-java-what-happens-when-an-object-fails-to-be - インスタンス化された) –
@JulienLopez欺瞞ではなく、編集を参照してください。 – noamtm