To prove initialization safety for immutable objects, I wrote a small program. Even though fields were final, second thread was able to view the half-constructed object being created by the first thread. Have I got the concept wrong or "object escaping" can cause it? Second thread first printed "10 null" and then after half of the iterations it started printing "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++;
        }
    }
}
 
     
    