JavaRush /Java Blog /Random-TW /雙大括號初始化
Joysi
等級 41

雙大括號初始化

在 Random-TW 群組發布

1.雙括號初始化

使用雙大括號初始化(以下簡稱雙大括號初始化)是一種 Java 工具,用於在聲明列表、集合和映射等集合的同時創建它們。
雙大括號初始化 - 1
當您需要具有固定元素的清單(例如支援的產品或貨幣單位的清單)時,在初始化清單的同時聲明該清單可以提高程式碼的可讀性。這就是雙括號初始化越來越受歡迎的原因,因為沒有其他標準方法可以在程式碼中同時初始化來建立集合。不幸的是,與其他程式語言不同,Java 不支援文字集合。由於這個限制,即使創建一個包含少量元素的不可修改列表,也會迫使我們以重複調用的形式編寫許多行程式碼,add()以添加所需的元素並進行最終包裝:
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(5);
list.add(7);
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
這是不必要的冗餘描述,可以簡化。讓我們以一種方便的方式填充靜態列表,即在初始化期間直接在靜態區塊中填充,這就是Double brace初始化將幫助我們的,允許我們將所有內容寫在一行中:
List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>() {{
        add(2);
        add(3);
        add(5);
}});
同樣,Double brace初始化會幫助我們填入值 和HashMap
Map<Integer, String> intToString = new HashMap<Integer, String>(){{
         put(1, "one");
         put(2, "two");
         put(3, "three");
 }};
這一切看起來都很優雅,但它有其缺點,這使得雙括號初始化成為一種反模式。我們將在下一章進一步討論它們。

雙括號初始化的優點和缺點。

Double大括號初始化使用匿名內部類別的創建。然而,最初隱藏在表面上的東西,Double brace初始化會創建一個類,並在每次使用它時進一步初始化其實例。此外,使用了對此私有類別的隱藏引用,這可能會導致記憶體洩漏。您也不能對泛型使用幽靈運算子(菱形運算子 < >),因為我們無法存取匿名類別的內部。
(譯者:再次更詳細地講:
在第一個之後{,創建了一個內部匿名類,在第二個之後,{在創建該類的實例時進行初始化,在該實例中我們可以訪問外部(相對於匿名)類。)
優點:
  1. 減少程式碼行數
  2. 在一個表達式中建立和初始化。
缺點:
  1. 建立一個對您隱藏的匿名類別。
  2. 每次我們使用它的實例時,這都會為我們帶來額外的費用。
  3. 每次創建對其的隱藏引用時,都可能導致記憶體洩漏。
結論:由於上述缺點以及雙大括號替代方案的存在,初始化在 Java 世界中被視為反模式。 拯救小貓

Java 中雙大括號初始化的替代方案

好消息是,在 Java 中還有其他方法可以實現相同的目標。我們可以使用 Collection 類別中的 Copy 建構子在一行程式碼中實作 ArrayList 的建立和初始化,如下所示:
List<Integer> list = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(2, 3, 5)));
Arrays.asList()將會傳回一個傳遞給ArrayList複製建構函式的固定長度清單。請記住從Arrays.asList()和傳回的固定長度清單之間的差異Collections.unmodifiableList():您無法新增或刪除ArrayList- 的元素,但您可以使用 來透過索引變更元素set(),而對於 所傳回的清單則無法執行此操作Collections.unmodifiableList()。如果你想獲得一個小列表,這是最好的方法,儘管它對於其他集合來說不太透明Set,所以你必須List在創建Set-a 之前創建它。但這仍然比雙括號初始化更好,因為在這種情況下,每次使用時都不會建立額外的內部匿名類別。如果您執行的是 Java 8,您還有另一種替代方法。JDK 8 Stream API 將透過將輸出Stream Factory方法組合到集合中來幫助您建立小型集合List
List<String> list = Collections.unmodifiableList(Stream.of("abc", "bcd", "cde").collect(toList()));
Set您可以使用以下Collectors.toSet()方法 代替Collectors.toList()
Set<String> set = Collections.unmodifiableSet(Stream.of("abc", "bcd", "cde").collect(toSet()));
順便說一句,Stream collect方法並不能保證它們產生的集合不會被更改。在 Java 8 中,它們傳回的集合(例如 - ArrayListHashSetHashMap)非常常見(我們可以更改它們),但這一事實可能會在未來的 JDK 版本中得到修正。Double brace這就是關於Java 初始化的全部內容。該模板對於測試和演示來說是可以接受的,但對於生產使用來說還不夠好。由於其固有的缺點,雙括號初始化如今已成為一種反模式,特別是考慮到可用的替代方案。我自己仍然使用這個構造來初始化靜態地圖,僅此而已。因為我更喜歡透過與建構函數中的創建相結合來List創建。如果我使用 Java 8 - 使用 Stream API 和. 相關文章:如果您喜歡本教程並且想要了解有關 Java 程式設計模式、原理和最佳實踐的更多信息,您可能還想查看我們網站上的其他文章。 推薦閱讀:如果您想了解更多有關模式和最佳實踐的信息,您應該閱讀Joshua Bloch 的《有效編程》,沒有一本書可以取代它。而如果你已經精通Java,並且正在尋找一本關於設計模式的書,其幽默的講授風格有趣且易於閱讀,請關注《Head First》。設計模式”CollectionsArray.asListcollect()
譯者:我特意提供了布洛赫原著的鏈接,因為它翻譯成俄語並不成功(例如,Builder = 構造函數)。
文章翻譯什麼是 Java 中的雙括號初始化?反模式範例(2015 年 10 月發布)。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION