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); }};
這里利用了內(nèi)部類語法,這種方式比先new出對象然后再進行依次add要方便、簡潔許多。該方法稱之為“雙括號初始化”(double brace initialization)。
對該方法的理解
以ArrayList的初始化為例,第一層花括號,首先對定義了一個繼承自ArrayList的匿名內(nèi)部類
ArrayList<String> friends = new ArrayList<String>() { // 這里什么操作都沒有,全部繼承自父類(ArrayList) };
第二層則是一個自定義的對象構(gòu)造塊(稱之為 非靜態(tài)初始化塊)
new ArrayList<String>() { // 這里什么操作都沒有,全部繼承自父類(ArrayList) };
我們通過new得到ArrayList的子類的實例化,然后上轉(zhuǎn)型為ArrayList的引用
ArrayList<String> friends = new ArrayList<String>() {{}};
- 我們得到的 friends 實際上是ArrayList的子類的引用,但在功能上沒有任何改變
- 相比于常規(guī)標準方式進行初始化要簡潔許多(但代碼可讀性相對會差)
效率問題
利用雙大括號初始化集合從效率上來說可能不如標準的集合初始化步驟。原因在于使用雙大括號初始化會導致內(nèi)部類文件的產(chǎn)生,而這個過程就會影響代碼的執(zhí)行效率。
首先查看不同初始化方式生成的.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運行結(jié)果:
1508379452224
1508379452784
運行時間為:560毫秒
第二段代碼Test2運行結(jié)果:
1508379671505
1508379671507
運行時間為:2毫秒
雖然說這個時間差距會根據(jù)電腦性能以及運行狀態(tài)有所變化,但也能說明雙大括號初始化方法要比常規(guī)方法用時長
綜上,(測試初始化數(shù)據(jù)較少(list未達到自增臨界點)的情況下)雙大括號初始化方法要比常規(guī)方法效率低:
1. 雙大括號初始化方法生成的.class文件要比常規(guī)方法多
2. 雙大括號初始化方法運行時間要比常規(guī)方法長
總結(jié)
到此這篇關(guān)于Java中雙大括號初始化的理解與使用的文章就介紹到這了,更多相關(guān)Java雙大括號初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決Springboot項目中很多頁面出現(xiàn)Whitelabel Error Page(404)的問題
最近在接手的前后端項目中發(fā)現(xiàn)其默認路徑不是主機+端口(如:http://localhost:3453/)的形式,很多頁面的訪問是加了一個層級,只要訪問頁面就會出現(xiàn)Whitelabel Error Page(404),所以本文給大家提供了解決方案,需要的朋友可以參考下2024-02-02Spring security BCryptPasswordEncoder密碼驗證原理詳解
這篇文章主要介紹了Spring security BCryptPasswordEncoder密碼驗證原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03