首頁 > 軟體

Java中雙大括號初始化的理解與使用

2022-06-20 14:01:21

偶然機會看到一種物件初始的方式:

    // 新建一個列表,並賦值 "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雙大括號初始化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com