Java中雙大括號初始化的理解與使用
偶然機會看到一種對象初始的方式:
// 新建一個列表,並賦值 "Harry","Tony","Tom" ArrayList<String> friends = new ArrayList<String>() {{ add("Harry"); add("Tony"); add("Tom"); }};
當然,對Map集合也用同種初始化方式:
// 新建一個Map,並賦值 Map<String, Object> cat = new HashMap<String, Object>() {{ put("name", "Tom"); put("age", 10); }};
這裡利用瞭內部類語法,這種方式比先new出對象然後再進行依次add要方便、簡潔許多。該方法稱之為“雙括號初始化”(double brace initialization)。
對該方法的理解
以ArrayList的初始化為例,第一層花括號,首先對定義瞭一個繼承自ArrayList的匿名內部類
ArrayList<String> friends = new ArrayList<String>() { // 這裡什麼操作都沒有,全部繼承自父類(ArrayList) };
第二層則是一個自定義的對象構造塊(稱之為 非靜態初始化塊)
new ArrayList<String>() { // 這裡什麼操作都沒有,全部繼承自父類(ArrayList) };
我們通過new得到ArrayList的子類的實例化,然後上轉型為ArrayList的引用
ArrayList<String> friends = new ArrayList<String>() {{}};
- 我們得到的 friends 實際上是ArrayList的子類的引用,但在功能上沒有任何改變
- 相比於常規標準方式進行初始化要簡潔許多(但代碼可讀性相對會差)
效率問題
利用雙大括號初始化集合從效率上來說可能不如標準的集合初始化步驟。原因在於使用雙大括號初始化會導致內部類文件的產生,而這個過程就會影響代碼的執行效率。
首先查看不同初始化方式生成的.class文件
例如以下代碼:
public class Test1 { public static void main(String[] args) { System.out.println(System.currentTimeMillis()); ArrayList<String> list1 = new ArrayList<String>() {{ add("Harry"); add("Tony"); add("Tom"); add("Jerry"); }}; ArrayList<String> list2 = new ArrayList<String>() {{ add("Harry"); add("Tony"); add("Tom"); add("Jerry"); }}; ArrayList<String> list3 = new ArrayList<String>() {{ add("Harry"); add("Tony"); add("Tom"); add("Jerry"); }}; ArrayList<String> list4 = new ArrayList<String>() {{ add("Harry"); add("Tony"); add("Tom"); add("Jerry"); }}; ArrayList<String> list5 = new ArrayList<String>() {{ add("Harry"); add("Tony"); add("Tom"); add("Jerry"); }}; …… …snip… …… ArrayList<String> list1000 = new ArrayList<String>() {{ add("Harry"); add("Tony"); add("Tom"); add("Jerry"); }}; System.out.println(System.currentTimeMillis()); } }
Test1編譯後生成的.class列表為:
Test1$1.class
Test1$2.class
Test1$3.class
Test1$4.class
Test1$5.class
……
…snip…
……
Test1$1000.class
Test1.class
生成瞭 1001個.class文件
public class Test2 { public static void main(String[] args) { System.out.println(System.currentTimeMillis()); ArrayList<String> list1 = new ArrayList<>(); list1.add("Harry"); list1.add("Tony"); list1.add("Tom"); list1.add("Jerry"); ArrayList<String> list2 = new ArrayList<>(); list2.add("Harry"); list2.add("Tony"); list2.add("Tom"); list2.add("Jerry"); ArrayList<String> list3 = new ArrayList<>(); list3.add("Harry"); list3.add("Tony"); list3.add("Tom"); list3.add("Jerry"); ArrayList<String> list4 = new ArrayList<>(); list4.add("Harry"); list4.add("Tony"); list4.add("Tom"); list4.add("Jerry"); ArrayList<String> list5 = new ArrayList<>(); list5.add("Harry"); list5.add("Tony"); list5.add("Tom"); list5.add("Jerry"); …… …snip… …… ArrayList<String> list1000 = new ArrayList<>(); list1000.add("Harry"); list1000.add("Tony"); list1000.add("Tom"); list1000.add("Jerry"); System.out.println(System.currentTimeMillis()); } }
Test2編譯後生成的.class列表為:
Test2.class
隻生成瞭1個.class文件
運行時間
第一段代碼Test1運行結果:
1508379452224
1508379452784
運行時間為:560毫秒
第二段代碼Test2運行結果:
1508379671505
1508379671507
運行時間為:2毫秒
雖然說這個時間差距會根據電腦性能以及運行狀態有所變化,但也能說明雙大括號初始化方法要比常規方法用時長
綜上,(測試初始化數據較少(list未達到自增臨界點)的情況下)雙大括號初始化方法要比常規方法效率低:
1. 雙大括號初始化方法生成的.class文件要比常規方法多
2. 雙大括號初始化方法運行時間要比常規方法長
總結
到此這篇關於Java中雙大括號初始化的理解與使用的文章就介紹到這瞭,更多相關Java雙大括號初始化內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Java中Lambda表達式的使用詳細教程
- Java面試崗常見問題之ArrayList和LinkedList的區別
- 詳細總結Java for循環的那些坑
- Java中關於泛型、包裝類及ArrayList的詳細教程
- 細數java for循環中的那些坑