Java map雙括號初始化方式的問題

關於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

本文永久更新連接地址http://www.linuxidc.com/Linux/2014-06/103535.htm

相關文章
相關標籤/搜索