關於Java雙括號的初始化凡是確實很方便,特別是在常量文件中,無可替代。以下所示:java
Map map = new HashMap() {
{
put("Name", "Unmi");
put("QQ", "1125535");
}
};linux
好處很明顯就是一目瞭然。這裏來羅列下此種方法的壞處,若是這個對象要串行化,可能會致使串行化失敗。web
1.此種方式是匿名內部類的聲明方式(不懂的下文有詳盡解釋),因此引用中持有着外部類的引用。因此當時串行化這個集合時外部類也會被不知不覺的串行化,當外部類沒有實現serialize接口時,就會報錯。json
2.上例中,實際上是聲明瞭一個繼承自Hashset的子類。然而有些串行化方法,例如要經過Gson串行化爲json,或者要串行化爲xml時,類庫中提供的方式,是沒法串行化Hashset或者HashMap的子類的,從而致使串行化失敗。解決辦法:從新初始化爲一個Hashset對象:spa
new HashMap(map);orm
這樣就能夠正常初始化了。xml
雙括號寫法的原理:htm
第一層括弧 實際是定義了一個內部匿名類 (Anonymous Inner Class),第二層括弧 其實是一個實例初始化塊 (instance initializer block),這個塊在內部匿名類構造時被執行。這個塊之因此被叫作「實例初始化塊」是由於它們被定義在了一個類的實例範圍內。對象
上面代碼若是是寫在 TestDoubleBrace 類中,編譯後你會看到會生成 TestDoubleBrace$1.class 文件,反編譯該文件內容是:繼承
final class com.unmi.TestDoubleBrace$1 extends java.util.HashMap{ //建立了一個 HashMap 的子類 TestDoubleBracke$1
com.unmi.TestDoubleBrace$1();
Code:
0: aload_0
1: invokespecial #8; //Method java/util/HashMap."":()V //{} 中的代碼放到了構造方法中去了
4: aload_0
5: ldc #10; //String Name
7: ldc #12; //String Unmi
9: invokevirtual #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
12: pop
13: aload_0
14: ldc #18; //String QQ
16: ldc #20; //String 1125535
18: invokevirtual #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
21: pop
22: return
}
編寫高質量代碼 改善Java程序的151個建議 PDF高清完整版 http://www.linuxidc.com/Linux/2014-06/103388.htm
Java 8簡明教程 http://www.linuxidc.com/Linux/2014-03/98754.htm
Java對象初始化順序的簡單驗證 http://www.linuxidc.com/Linux/2014-02/96220.htm
Java對象值傳遞和對象傳遞的總結 http://www.linuxidc.com/Linux/2012-12/76692.htm
Java對象序列化ObjectOutputStream和ObjectInputStream示例 http://www.linuxidc.com/Linux/2012-08/68360.htm