Co to jest składnia inicjalizacji Double Brace ( {{ ... }}
) w Javie?
java
initialization
double-brace-initialize
sgokhales
źródło
źródło
Odpowiedzi:
Orteza inicjalizacji tworzy podwójne anonimową klasy pochodzący od określonej klasy (na zewnętrznych wzmocnienia), i stanowi blok initialiser w tej klasie (na wewnętrzne wzmocnienia). na przykład
Zauważ, że efektem tej inicjalizacji podwójnego nawiasu klamrowego jest tworzenie anonimowych klas wewnętrznych. Utworzona klasa ma domyślny
this
wskaźnik do otaczającej klasy zewnętrznej. Chociaż zwykle nie jest to problemem, może powodować żal w niektórych okolicznościach, np. Podczas serializacji lub zbierania śmieci, i warto o tym wiedzieć.źródło
Za każdym razem, gdy ktoś używa inicjalizacji podwójnego nawiasu klamrowego, kotek ginie.
Oprócz tego, że składnia jest raczej nietypowa i nie bardzo idiomatyczna (smak jest oczywiście dyskusyjny), niepotrzebnie stwarzasz dwa znaczące problemy w swojej aplikacji, o których niedawno pisałem bardziej szczegółowo tutaj .
1. Tworzysz zbyt wiele anonimowych klas
Za każdym razem, gdy używasz inicjalizacji podwójnego nawiasu klamrowego, tworzona jest nowa klasa. Np. Ten przykład:
... stworzy te klasy:
To dość duże obciążenie dla twojego programu ładującego klasy - na darmo! Oczywiście nie zajmie to dużo czasu inicjalizacji, jeśli zrobisz to raz. Ale jeśli zrobisz to 20 000 razy w całej aplikacji korporacyjnej ... cała ta pamięć sterty tylko na odrobinę cukru składniowego?
2. Potencjalnie tworzysz wyciek pamięci!
Jeśli weźmiesz powyższy kod i zwrócisz mapę z metody, osoby wywołujące tę metodę mogą nieświadomie trzymać się bardzo ciężkich zasobów, których nie można wyrzucać. Rozważ następujący przykład:
Zwrócony
Map
będzie teraz zawierał odwołanie do załączającej instancjiReallyHeavyObject
. Prawdopodobnie nie chcesz ryzykować, że:Zdjęcie z http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/
3. Możesz udawać, że Java ma literały map
Aby odpowiedzieć na twoje pytanie, ludzie używali tej składni, by udawać, że Java ma coś w rodzaju literałów map, podobnych do istniejących literałów tablic:
Niektóre osoby mogą uznać to za stymulujące syntaktycznie.
źródło
{{...}}
i zadeklarowany jakostatic
pole, nie powinno być żadnego przecieku pamięci, tylko jedna anonimowa klasa i brak odwołań do załączonej instancji, prawda?Map.of()
ten cel, więc będzie lepsze rozwiązanieReallyHeavyObject
. Również anonimowe klasy wewnętrzne przechwytują wszystkie zmienne lokalne używane w treści klasy, więc jeśli użyjesz nie tylko stałych do zainicjowania kolekcji lub map z tym wzorcem, instancje klasy wewnętrznej przechwycą wszystkie i nadal będą się do nich odwoływać, nawet jeśli faktycznie zostaną usunięte z kolekcja lub mapa. Tak więc w takim przypadku te instancje nie tylko potrzebują dwa razy tyle pamięci, ile potrzeba do referencji, ale mają kolejny wyciek pamięci w tym zakresie.Na przykład:
Jak to działa
Pierwszy nawias klamrowy tworzy nową Anonimową klasę wewnętrzną. Te klasy wewnętrzne są w stanie uzyskać dostęp do zachowania swojej klasy nadrzędnej. W naszym przypadku tworzymy podklasę klasy HashSet, więc ta klasa wewnętrzna może używać metody put ().
I drugie zestaw szelki są tylko instancji inicjalizatory. Jeśli przypomnisz podstawowe koncepcje Java, możesz łatwo powiązać bloki inicjatora instancji z inicjalizatorami statycznymi dzięki podobnemu nawiasowi klamrowemu, jak struct. Jedyną różnicą jest to, że inicjator statyczny jest dodawany do słowa kluczowego static i jest uruchamiany tylko raz; bez względu na to, ile obiektów utworzysz.
więcej
źródło
Zabawna aplikacja inicjalizacji podwójnego nawiasu klamrowego znajduje się tutaj Tablica Dwemthy w Javie .
Fragment
A teraz przygotuj się na
BattleOfGrottoOfSausageSmells
i… masywny bekon!źródło
Myślę, że ważne jest, aby podkreślić, że nie ma czegoś takiego jak „inicjalizacja podwójnego nawiasu klamrowego” w Javie . Witryna Oracle nie ma tego terminu. W tym przykładzie zastosowano dwie funkcje: anonimową klasę i blok inicjujący. Wygląda na to, że stary blok inicjalizujący został zapomniany przez programistów i powoduje pewne zamieszanie w tym temacie. Cytat z dokumentów Oracle :
Bloki inicjalizujące na przykład zmienne wyglądają jak statyczne bloki inicjalizujące, ale bez słowa kluczowego static:
źródło
1- Nie ma czegoś takiego jak podwójne nawiasy klamrowe:
Chciałbym zauważyć, że nie ma czegoś takiego jak inicjalizacja podwójnego nawiasu klamrowego. Jest tylko normalny tradycyjny blok inicjujący jeden nawias klamrowy. Drugi blok nawiasów klamrowych nie ma nic wspólnego z inicjalizacją. Odpowiedzi mówią, że te dwa nawiasy inicjują coś, ale tak nie jest.
2- Nie chodzi tylko o anonimowe klasy, ale wszystkie klasy:
prawie wszystkie odpowiedzi mówią, że jest to rzecz używana podczas tworzenia anonimowych klas wewnętrznych. Myślę, że ludzie czytający te odpowiedzi będą mieli wrażenie, że jest to wykorzystywane tylko podczas tworzenia anonimowych klas wewnętrznych. Ale jest stosowany we wszystkich klasach. Czytanie tych odpowiedzi wygląda jak nowa funkcja specjalna poświęcona anonimowym klasom i myślę, że to jest mylące.
3- Celem jest po prostu umieszczenie nawiasów jeden za drugim, a nie nowa koncepcja:
W dalszej części pytanie dotyczy sytuacji, gdy drugi nawias otwierający jest tuż po pierwszym nawiasie otwierającym. Kiedy jest używany w normalnej klasie, zwykle między dwoma nawiasami klamrowymi jest jakiś kod, ale jest to całkowicie to samo. Chodzi więc o umieszczenie nawiasów. Sądzę więc, że nie powinniśmy mówić, że jest to nowa ekscytująca rzecz, ponieważ wszyscy wiemy, ale po prostu napisaliśmy z pewnym kodem między nawiasami. Nie powinniśmy tworzyć nowej koncepcji zwanej „inicjalizacją podwójnego nawiasu klamrowego”.
4- Tworzenie zagnieżdżonych anonimowych klas nie ma nic wspólnego z dwoma nawiasami klamrowymi:
nie zgadzam się z argumentem, że tworzysz zbyt wiele anonimowych klas. Nie tworzysz ich z powodu bloku inicjalizacji, ale tylko dlatego, że je tworzysz. Zostałyby one utworzone, nawet gdybyś nie użył inicjalizacji dwóch nawiasów klamrowych, więc te problemy wystąpiłyby nawet bez inicjalizacji ... Inicjalizacja nie jest czynnikiem tworzącym inicjowane obiekty.
źródło
Aby uniknąć wszystkich negatywnych skutków inicjalizacji podwójnego nawiasu, takich jak:
rób kolejne rzeczy:
Przykład:
Stosowanie:
Zalety:
Niedogodności:
W rezultacie mamy najprostszy wzór konstruktora Java.
Zobacz wszystkie próbki na github: java-sf-builder-simple-example
źródło
Jest to - między innymi zastosowaniami - skrót do inicjowania kolekcji. Ucz się więcej ...
źródło
masz na myśli coś takiego?
jest to inicjalizacja listy tablic w czasie tworzenia (hack)
źródło
Możesz umieścić kilka instrukcji Java jako pętlę, aby zainicjować kolekcję:
Ale ten przypadek wpływa na wydajność, sprawdź tę dyskusję
źródło
Jak wskazał @Lukas Eder, należy unikać podwójnej nawiasy klamrowej inicjalizacji kolekcji.
Tworzy anonimową klasę wewnętrzną, a ponieważ wszystkie klasy wewnętrzne zachowują odwołanie do instancji nadrzędnej, może - i na 99% prawdopodobne - zapobiegnie odśmiecaniu, jeśli do tych obiektów kolekcji odwołuje się więcej obiektów niż tylko deklarująca.
Java 9 wprowadziła metody wygody
List.of
,Set.of
orazMap.of
, które powinny być używane zamiast. Są szybsze i bardziej wydajne niż inicjator z podwójną klamrą.źródło
Pierwszy nawias klamrowy tworzy nową klasę anonimową, a drugi zestaw nawiasów tworzy inicjalizatory instancji, takie jak blok statyczny.
Jak zauważyli inni, korzystanie z niego nie jest bezpieczne.
Jednak zawsze możesz użyć tej alternatywy do inicjowania kolekcji.
źródło
Wygląda na to, że jest taki sam jak w przypadku słowa kluczowego with, tak popularnego we flashu i vbscript. To metoda zmiany tego, co
this
jest i nic więcej.źródło
this
jest. Składnia po prostu tworzy anonimową klasę (więc każde odniesienie dothis
niej odnosi się do obiektu tej nowej anonimowej klasy), a następnie używa bloku inicjującego{...}
w celu zainicjowania nowo utworzonej instancji.