部分內容參考:
http://blog.csdn.net/fgakjfd/article/details/5282646
延遲初始化
普通模式
private final FieldType field = computeFieldValue();
private FieldType field;
public synchronized FieldType getField() {
if (field == null) {
field = computeFieldValue();
}
return field;
}
上面兩種方式用到靜態域類似的,加上static關鍵字修飾即可。
lazy initialization holder class 模式
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
public static FieldType getField() {
return FieldHolder.field;
}
當調用getField方法時,第一次讀取FieldHolder.field,導致靜態內部類進行初始化。這種模式的關鍵在於,getField方法不需要同步,並且只執行一個域的訪問,因此並沒有增加更多的成本。這裏實際上利用了靜態內部類在使用的時候才進行初始化這個特點。靜態內部類
如果你不需要內部類對象與其外圍類對象之間有聯繫,那你可以將內部類聲明爲static。這通常稱爲嵌套類(nested class)。Static Nested Class是被聲明爲靜態(static)的內部類,它可以不依賴於外部類實例被實例化。而通常的內部類需要在外部類實例化後才能實例化。想要理解static應用於內部類時的含義,你就必須記住,普通的內部類對象隱含地保存了一個引用,指向創建它的外圍類對象。然而,當內部類是static的時,就不是這樣了。嵌套類意味着:
1. 嵌套類的對象,並不需要其外圍類的對象。
2. 不能從嵌套類的對象中訪問非靜態的外圍類對象。
另外,需要注意的是,靜態內部類只有在第一次使用的時候纔會被加載。
雙重檢查模式
如果從性能角度考慮,需要對實例域進行延遲初始化,可以使用這種模式。這種模式避免了在初始化之後,再次訪問這個域時的鎖定開銷(在普通的方法裏面,會使用synchronized對方法進行同步,每次訪問方法的時候都要進行鎖定)。
這種模式的思想是:兩次檢查域的值,第一次檢查時不鎖定,看看其是否初始化;第二次檢查時鎖定。只用當第二次檢查時,表明其沒有被初始化,纔會調用computeFieldValue方法對其進行初始化。如果已經被初始化了,就不會鎖定了,另外該域被聲明爲volatile非常重要。
private volatile FieldType field;
public FieldType getField() {
FieldType result = field;
if (result == null) {
synchronized (this) {
result = field;
if (result == null) {
field = result = computeFieldValue();
}
}
}
return result;
}
在上面的代碼中,事實上,只要該域被初始化以後,無論如何再也不會進入第二次的條件語句判斷,也就是說被初始化以後,訪問的時候再也不會被synchronized鎖定。