如果你接觸過不同的語言,從文法和代碼層面來說,java 是一種不折不扣的“臃腫、啰嗦”的語言,從另一方面來說這種臃腫和啰嗦也展現了它嚴謹的一面,作為适合建構大型、複雜項目的理由之一。
1、hashmap 初始化的文藝寫法
hashmap 是一種常用的資料結構,一般用來做資料字典或者 hash 查找的容器。普通青年一般會這麼初始化:
看完這段代碼,很多人都會覺得這麼寫太啰嗦了,對此,文藝青年一般這麼來了:
嗯,看起來優雅了不少,一步到位,一氣呵成的趕腳。然後問題來了,有童鞋會問:納尼?這裡的雙括号到底什麼意思,什麼用法呢?哈哈,其實很簡單,看看下面的代碼你就知道啥意思了。
note:關于 static 的作用與用法如果不了解,請參考:
也就是說第一層括弧實際是定義了一個匿名内部類 (anonymous inner class),第二層括弧實際上是一個執行個體初始化塊 (instance initializer block),這個塊在内部匿名類構造時被執行。這個塊之是以被叫做“執行個體初始化塊”是因為它們被定義在了一個類的執行個體範圍内。
上面代碼如果是寫在 test 類中,編譯後你會看到會生成 test$1.class 檔案,反編譯該檔案内容:
2、推而廣之
這種寫法,推而廣之,在初始化 arraylist、set 的時候都可以這麼玩,比如你還可以這麼玩:
3、java7:增加對 collections 的支援
在 java 7 中你可以像 ruby, perl、python 一樣建立 collections 了。
note:這些集合是不可變的。
ps:由于原文[5]作者并沒有标出 java 7 哪個小版本号引入的這些新特性,對于留言報錯的同學,請嘗試大于 1.7.0_09 或者 java8 試試?
4、文藝寫法的潛在問題
文章開頭提到的文藝寫法的好處很明顯就是一目了然。這裡來羅列下此種方法的壞處,如果這個對象要串行化,可能會導緻串行化失敗。
1.此種方式是匿名内部類的聲明方式,是以引用中持有着外部類的引用。是以當時串行化這個集合時外部類也會被不知不覺的串行化,當外部類沒有實作serialize接口時,就會報錯。
2.上例中,其實是聲明了一個繼承自hashmap的子類。然而有些串行化方法,例如要通過gson串行化為json,或者要串行化為xml時,類庫中提供的方式,是無法串行化hashset或者hashmap的子類的,進而導緻串行化失敗。解決辦法:重新初始化為一個hashmap對象:
new hashmap(map);
這樣就可以正常初始化了。
5、執行效率問題
當一種新的工具或者寫法出現時,猿們都會來一句:性能怎麼樣?(這和男生談論妹紙第一句一般都是:“長得咋樣?三圍多少?”一個道理:))
關于這個兩種寫法我這邊筆記本上測試文藝寫法、普通寫法分别建立 10,000,000 個 map 的結果是 1217、1064,相差 13%。
6、由執行個體初始化塊聯想到的一些變量初始化問題
從代碼上看,a 為什麼可以不先聲明類型?你覺得 a、b、c 的值分别是多少?能說明理由麼?
tips:如果你對這塊機制不了解,建議試着反編譯一下位元組碼檔案。
6.1 測試源碼
6.2 位元組碼反編譯:
6.3 output:
7、refer: