首先觀察下面代碼,並想下輸出結果是什麼
public class SinglePattern{
private static SinglePattern instance = new SinglePattern();//在類的裝載就直接實例化
public static int a;
public static int b = 2;
private SinglePattern(){
a++;
b++;
}
public static SinglePattern getInstance() {
return instance;
}
public static void main(String[] args) {
SinglePattern ins = SinglePattern.getInstance();
System.out.println("a:="+ins.a);
System.out.println("b:="+ins.b);
}
}
上面就是一個單例模式唄
然後我不做任何修改,改變類實例化的一行代碼的位置,想想輸出結果是什麼?
public class SinglePattern{
public static int a;
public static int b = 2;
private static SinglePattern instance = new SinglePattern();//在類的裝載就直接實例化
private SinglePattern(){
a++;
b++;
}
public static SinglePattern getInstance() {
return instance;
}
public static void main(String[] args) {
SinglePattern ins = SinglePattern.getInstance();
System.out.println("a:="+ins.a);
System.out.println("b:="+ins.b);
}
}
想到結果了沒??
第一個運行結果爲:
第二個運行結果爲:
WTF?
就改變一行代碼的位置,沒有其它大的改動,就結果不一樣了!!
其實這是類加載過程產生的問題,對類加載過程詳細瞭解。可以參考:https://blog.csdn.net/weijifeng_/article/details/79894742
對於兩個代碼分析詳解
1 .準備階段
instance = null;
a = 0;
b = 0;
2 .初始化階段
new SinglePattern() ; a = 1; b = 1;
public static int a; a沒有指定值,就是上一步的1
public static int b = 2; b有指定初始值,初始化階段時,b = 2;
所以這就是第一種執行結果爲a = 1, b = 2的原因了
1 .準備階段
instance = null;
a = 0;
b = 0;
2 .初始化階段
public static int a; a沒有指定值,就是上一步的0
public static int b = 2; b有指定初始值,初始化階段時,b = 2;
new SinglePattern() ; a = 1; b = 3;
這就是產生結果不一樣的原因了!
類加載的準備階段和初始化階段都嚴格執行自己的工作,並且在初始化階段,嚴格按照指令從上到下的順序就行內存值分配
所以在瞭解裝載的過程,就應該清楚自己取什麼階段的值,保證取值不會發生錯誤