問題
Java中的Double Brace初始化文法({{ ... }})是什麼?
#1 熱門回答(208 贊)
每當有人使用雙支撐初始化時,一隻小貓就會被殺死。
除了文法相當不尋常并且不是真正的慣用語(當然味道有争議)之外,你在應用程式中不必要地建立了兩個重要問題,which I've just recently blogged about in more detail here。
1.你建立了太多的匿名類
每次使用雙括号初始化時,都會生成一個新類。例如。這個例子:
Map source = new HashMap(){{
put("firstName", "John");
put("lastName", "Smith");
put("organizations", new HashMap(){{
put("0", new HashMap(){{
put("id", "1234");
}});
put("abc", new HashMap(){{
put("id", "5678");
}});
}});
}};
...将産生這些類:
Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class
這對你的類加載器來說是一個相當大的開銷 - 什麼都沒有!當然,如果你這樣做一次,它将不需要太多的初始化時間。但是,如果你在整個企業應用程式中執行此操作20'000次...所有堆記憶體隻是為了一點"文法糖"?
2.你可能會造成記憶體洩漏!
如果你使用上面的代碼并從方法傳回該映射,那麼該方法的調用者可能會毫無疑問地保留非常繁重的資源,而這些資源無法進行垃圾回收。請考慮以下示例:
public class ReallyHeavyObject {
// Just to illustrate...
private int[] tonsOfValues;
private Resource[] tonsOfResources;
// This method almost does nothing
public Map quickHarmlessMethod() {
Map source = new HashMap(){{
put("firstName", "John");
put("lastName", "Smith");
put("organizations", new HashMap(){{
put("0", new HashMap(){{
put("id", "1234");
}});
put("abc", new HashMap(){{
put("id", "5678");
}});
}});
}};
return source;
}
}
傳回的Map現在将包含對封閉執行個體ReallyHeavyObject的引用。你可能不想冒這個風險:
3.你可以假裝Java有 Map 文字
為了回答你的實際問題,人們一直在使用這種文法假裝Java有類似于現有數組文字的 Map 文字:
String[] array = { "John", "Doe" };
Map map = new HashMap() {{ put("John", "Doe"); }};
有些人可能會發現這種文法刺激。
#2 熱門回答(203 贊)
雙括号初始化建立一個從指定類(theouterbraces)派生的匿名類,并在該類中提供初始化塊(theinnerbraces)。例如
new ArrayList() {{
add(1);
add(2);
}};
請注意,使用此雙括号初始化的效果是你正在建立匿名内部類。建立的類具有對周圍外部類的隐式this指針。雖然通常不是問題,但在某些情況下會導緻悲傷,例如:在序列化或垃圾收集時,值得注意這一點。
#3 熱門回答(34 贊)
第一個大括号建立一個新的匿名内部類。
第二組大括号建立一個執行個體初始值設定項,如Class中的靜态塊。
例如:
public class TestHashMap {
public static void main(String[] args) {
HashMap map = new HashMap(){
{
put("1", "ONE");
}{
put("2", "TWO");
}{
put("3", "THREE");
}
};
Set keySet = map.keySet();
for (String string : keySet) {
System.out.println(string+" ->"+map.get(string));
}
}
}
工作原理
First brace建立一個新的匿名内部類。這些内部類能夠通路其父類的行為。是以,在我們的例子中,我們實際上是在建立一個HashSet類的子類,是以這個内部類能夠使用add()方法。
And第二組大括号隻是執行個體初始化器。如果你提醒核心Java概念,那麼你可以輕松地将執行個體初始化程式塊與靜态初始化程式相關聯,因為類似于大寫字母結構。唯一的差別是靜态初始化程式添加了靜态關鍵字,并且隻運作一次;無論你建立多少個對象。
more