4

为了证明不可变对象的初始化安全性,我编写了一个小程序。即使字段是最终的,第二个线程也能够查看由第一个线程创建的半构造对象。我的概念是否错误或“对象转义”会导致它?第二个线程首先打印“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 在构造函数中泄漏 this

于 2013-09-22T20:02:45.783 回答