As is known guarant that if we have some object reference and this reference has final field - we will see all reachable fields from final field(at least when constructor was finished)
example 1:
class Foo{
private final Map map;
Foo(){
map = new HashMap();
map.put(1,"object");
}
public void bar(){
System.out.println(map.get(1));
}
}
As I undertand at this case we have guarantee that bar() method always output object because:
1. I listed full code of class Foo and map is final;
2. If some thread will see reference of Foo and this reference != null, then we have guarantees that reachable from final map reference value will be actual.
also I think that
Example 2:
class Foo {
private final Map map;
private Map nonFinalMap;
Foo() {
nonFinalMap = new HashMap();
nonFinalMap.put(2, "ololo");
map = new HashMap();
map.put(1, "object");
}
public void bar() {
System.out.println(map.get(1));
}
public void bar2() {
System.out.println(nonFinalMap.get(2));
}
}
here we have same gurantees about bar() method but bar2 can throw NullPointerException despite nonFinalMap assignment occurs before map assignment.
I want to know how about volatile:
Example 3:
class Foo{
private volatile Map map;
Foo(){
map = new HashMap();
map.put(1,"object");
}
public void bar(){
System.out.println(map.get(1));
}
}
As I understand bar() method cannot throw NullPoinerException but it can print null; (I am fully not sure about this aspect)
Example 4:
class Foo {
private volatile Map map;
private Map nonVolatileMap;
Foo() {
nonVolatileMap= new HashMap();
nonVolatileMap.put(2, "ololo");
map = new HashMap();
map.put(1, "object");
}
public void bar() {
System.out.println(map.get(1));
}
public void bar2() {
System.out.println(nonFinalMap.get(2));
}
}
I think here we have same gurantees about bar() method also bar2() cannot throw NullPointerException because nonVolatileMap assignment written higher volatile map assignment but it can output null
Added after Elliott Frisch comment
Publication through race example:
public class Main {
private static Foo foo;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
foo = new Foo();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (foo == null) ; // empty loop
foo.bar();
}
}).start();
}
}
Please proove or correct my comments to code snippets.