知られているように、オブジェクト参照があり、この参照に最終フィールドがある場合、最終フィールドから到達可能なすべてのフィールドが表示されます(少なくともコンストラクターが終了したとき)
例 1:
class Foo{
private final Map map;
Foo(){
map = new HashMap();
map.put(1,"object");
}
public void bar(){
System.out.println(map.get(1));
}
}
この場合、次の理由により、メソッドが常に出力されることが保証されていますbar()
。1
.クラスの完全なコードをリストし、マップは最終です。2. 一部のスレッドが参照を参照し、この参照が != null である場合、最終参照値から到達可能であることが保証されます。object
Foo
Foo
map
私もそう思います
例 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));
}
}
bar()
ここでは、メソッドについて同じ保証がありますが、割り当ての前に割り当てが発生してもbar2
スローでき ます。NullPointerException
nonFinalMap
map
揮発性について知りたい:
例 3:
class Foo{
private volatile Map map;
Foo(){
map = new HashMap();
map.put(1,"object");
}
public void bar(){
System.out.println(map.get(1));
}
}
私が理解しているように、bar()
メソッドはスローできませんNullPoinerException
が、印刷できますnull
。(私はこの点について完全に確信が持てません)
例 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));
}
}
ここでは、割り当てがより高い揮発性のマップ割り当てを記述したため、bar()
メソッドもbar2()
スローできないという同じ保証があると思いますが、nullを出力できますNullPointerException
nonVolatileMap
エリオット・フリッシュのコメントの後に追加
レースの例による出版:
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();
}
}
コード スニペットに対する私のコメントを証明または修正してください。