4

不変オブジェクトの初期化の安全性を証明するために、小さなプログラムを作成しました。フィールドは最終的なものでしたが、2 番目のスレッドは、最初のスレッドによって作成された半分構築されたオブジェクトを表示できました。概念が間違っているか、「オブジェクトのエスケープ」が原因でしょうか? 2 番目のスレッドは、最初に「10 null」を出力し、半分の繰り返しの後、「10 apple」の出力を開始しました。

package test;

import java.util.ArrayList;
import java.util.List;

public final class ObjectEscape implements Runnable {

    private final int a;
    private final String b;

    //this list is defined somewhere else
    public static volatile List<ObjectEscape> globalList = new ArrayList<ObjectEscape>();

    public ObjectEscape () throws InterruptedException {

        a = 10;
        globalList.add(this);
        Thread.sleep(10);
        b = "apple";
        System.out.println("done");

    }

    public ObjectEscape(int a) {
        this.a = 1;
        b = "";
    }

    public static void main(String are[]) throws InterruptedException{

        Thread t = new Thread(new ObjectEscape(1));
        t.start();
        ObjectEscape oe1 = new ObjectEscape();


    }


    @Override
    public void run() {
        int i=0;
        while(i<10) {
            if(globalList.get(0) != null)
            System.out.println(globalList.get(0).a+"        "+globalList.get(0).b);
        i++;
        }
    }
}
4

1 に答える 1

9

finalコンストラクターの呼び出しが完了すると、フィールドは初期化されていることが保証されます。当然、「これを漏らす」と、この保証の価値が覆されます。

globalList.add(this); // ObjectEscape.<init> has not finished yet

参照: Java がコンストラクターでこれをリークしている

于 2013-09-22T20:02:45.783 に答える