1. Inicjalizacja podwójnego nawiasu klamrowego
Inicjalizacja przy użyciu podwójnych nawiasów klamrowych (
zwana dalej inicjalizacją podwójnych nawiasów ) to narzędzie Java służące do tworzenia kolekcji takich jak lista, zestaw i mapa jednocześnie z ich deklaracją.
Gdy potrzebujesz list ze stałymi elementami, takimi jak lista obsługiwanych produktów czy walut, zadeklarowanie listy jednocześnie z jej inicjalizacją poprawia czytelność kodu. Właśnie dlatego inicjalizacja z podwójnymi nawiasami zyskuje na popularności, ponieważ nie ma innych standardowych metod tworzenia kolekcji z jednoczesną inicjalizacją w kodzie. Niestety, w przeciwieństwie do innych języków programowania, Java nie obsługuje kolekcji literałów. Ze względu na to ograniczenie utworzenie niemodyfikowalnej listy nawet
z niewielką liczbą elementów zmusza nas do napisania wielu linijek kodu w formie powtarzających się wywołań
add()
w celu dodania żądanych elementów z ostatecznym opakowaniem:
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(5);
list.add(7);
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
Jest to niepotrzebnie zbędny opis, który można uprościć. Listy statyczne wypełniajmy w dogodny dla nas sposób, czyli bezpośrednio w blokach statycznych podczas inicjalizacji, w czym
Double brace
pomoże nam inicjalizacja, pozwalająca nam napisać wszystko w jednej linijce:
List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>() {{
add(2);
add(3);
add(5);
}});
Podobnie
Double brace
inicjalizacja pomoże nam wypełnić wartości i
HashMap
:
Map<Integer, String> intToString = new HashMap<Integer, String>(){{
put(1, "one");
put(2, "two");
put(3, "three");
}};
Wszystko wygląda elegancko, ale ma swoje wady, które sprawiają, że inicjalizacja z podwójnym nawiasem jest anty-wzorem. Przyjrzymy się im bliżej w następnym rozdziale.
Plusy i minusy inicjalizacji podwójnego nawiasu klamrowego.
Double
Inicjalizacja nawiasów klamrowych wykorzystuje utworzenie anonimowej klasy
wewnętrznej . Jednak to, co początkowo jest ukryte na powierzchni,
Double brace
inicjalizacja tworzy klasę z dalszą inicjalizacją jej instancji za każdym razem, gdy jej używasz. Dodatkowo stosowane jest ukryte odniesienie do tej prywatnej klasy, co może nas naprowadzić na możliwe wycieki pamięci. Nie możesz także używać operatora widma dla typów generycznych (operator rombu < >), ponieważ nie możemy uzyskać dostępu do wnętrza anonimowej klasy.
(Od tłumacza: Jeszcze bardziej szczegółowo:
po pierwszej { tworzona jest wewnętrzna anonimowa klasa, po drugiej { następuje inicjalizacja podczas tworzenia instancji klasy, w której mamy dostęp do pól i metod zewnętrznej ( w stosunku do klasy anonimowej). |
Plusy:
- Redukcja linii w kodzie
- Tworzenie i inicjalizacja w jednym wyrażeniu.
Wady:
- Tworzenie anonimowej klasy ukrytej przed tobą.
- Co kosztuje nas dodatkowe koszty za jego instancję za każdym razem, gdy z niego korzystamy.
- Za każdym razem tworzone jest ukryte odniesienie do niego, co może prowadzić do wycieków pamięci.
Werdykt: Ze względu na powyższe wady i istnienie alternatyw dla podwójnych nawiasów klamrowych, inicjalizacja jest postrzegana jako antywzorzec w świecie Java.
Alternatywy dla inicjalizacji podwójnych nawiasów klamrowych w Javie
Dobra wiadomość jest taka, że istnieją inne sposoby osiągnięcia tych samych celów w Javie. Możemy zaimplementować w jednym wierszu kodu utworzenie i inicjalizację ArrayList za pomocą konstruktora Copy z klasy Collection, jak pokazano poniżej:
List<Integer> list = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(2, 3, 5)));
Arrays.asList()
zwróci nam listę o stałej długości przekazanej
ArrayList
konstruktorowi kopiującemu. Pamiętaj o różnicy pomiędzy listami o stałej długości zwracanymi przez
Arrays.asList()
i
Collections.unmodifiableList()
: nie możesz dodawać ani usuwać elementów
ArrayList
- , ale możesz zmieniać element według indeksu za pomocą
set()
, czego nie można zrobić w przypadku listy zwróconej przez
Collections.unmodifiableList()
. Jeśli chcesz uzyskać małą listę, jest to najlepszy sposób, chociaż będzie mniej przejrzysty dla
Set
innych kolekcji, więc będziesz musiał ją utworzyć
List
przed utworzeniem
Set
opcji -a. Jest to jednak nadal lepsze niż inicjalizacja z podwójnym nawiasem klamrowym, ponieważ w tym przypadku dodatkowa wewnętrzna anonimowa klasa nie jest tworzona za każdym razem, gdy jest używana. Jeśli używasz Java 8, masz inną alternatywną metodę. Interfejs API strumienia JDK 8 pomoże Ci stworzyć małe kolekcje, łącząc
Stream Factory
metody wyjściowe w kolekcję
List
:
List<String> list = Collections.unmodifiableList(Stream.of("abc", "bcd", "cde").collect(toList()));
Zamiast tego
Set
możesz użyć
Collectors.toSet()
metody
Collectors.toList()
jak poniżej:
Set<String> set = Collections.unmodifiableSet(Stream.of("abc", "bcd", "cde").collect(toSet()));
Nawiasem mówiąc,
Stream collect
metody nie gwarantują, że generowane przez nie zbiory będą chronione przed zmianami. W Javie 8 zwracane przez nie kolekcje (takie jak -
ArrayList
,
HashSet
i
HashMap
) są dość powszechne (możemy je zmienić), ale fakt ten może zostać poprawiony w przyszłych wydaniach JDK. To wszystko na razie o
Double brace
inicjalizacji w Javie. Ten szablon jest akceptowalny w przypadku testów i wersji demonstracyjnych, ale nie jest wystarczająco dobry do użytku produkcyjnego. Ze względu na swoje nieodłączne wady, inicjalizacja z podwójnym nawiasem stała się obecnie antywzorcem, szczególnie biorąc pod uwagę dostępne alternatywy. Ja sam nadal wykorzystuję tę konstrukcję do inicjalizacji map statycznych i tyle. Wolę bowiem
List
tworzyć
Collections
poprzez połączenie z tworzeniem
Array.asList
w jego konstruktorze. A jeśli użyję Java 8 - projekt wykorzystujący Stream API i
collect()
.
Powiązane artykuły: Jeśli podobał Ci się ten samouczek i chcesz dowiedzieć się więcej o wzorcach, zasadach i najlepszych praktykach programowania w języku Java, możesz także zapoznać się z innymi artykułami w naszej
witrynie .
Zalecana lektura: Jeśli chcesz dowiedzieć się więcej o wzorcach i najlepszych praktykach, przeczytaj
Efektywne programowanie Joshuy Blocha , żadna książka nie zastąpi jej. A jeśli znasz już biegle Javę i szukasz książki o wzorcach projektowych, której humorystyczny sposób prezentacji jest ciekawy i łatwy w odbiorze, zwróć uwagę na
„Head First. Wzorce projektowe" .
Od tłumacza: Celowo podałem link do oryginalnej książki Blocha, gdyż jej tłumaczenie na rosyjski nie powiodło się (np. Builder = konstruktor). |
Tłumaczenie artykułu Co to jest inicjalizacja podwójnego nawiasu w Javie? Przykład przeciwdziałania wzorowi (opublikowany w październiku 2015 r.).
GO TO FULL VERSION