O ile rozumiem, „blok inicjalizacji statycznej” służy do ustawiania wartości pola statycznego, jeśli nie można tego zrobić w jednym wierszu.
Ale nie rozumiem, dlaczego potrzebujemy do tego specjalnego bloku. Na przykład deklarujemy pole jako statyczne (bez przypisania wartości). A następnie napisz kilka wierszy kodu, które generują i przypisują wartość do wyżej zadeklarowanego pola statycznego.
Dlaczego potrzebujemy tych linii w specjalnym bloku, takim jak static {...}
:?
{...}
vsstatic {...}
. (w takim przypadku Jon Skeet zdecydowanie lepiej odpowiedział na twoje pytanie)Odpowiedzi:
Blok niestatyczny:
Pobiera wywołanie za każdym razem, gdy tworzona jest instancja klasy. Statyczny blok tylko jest wywoływana raz , kiedy sama klasa jest inicjowany, bez względu na to jak wiele obiektów tego typu utworzyć.
Przykład:
To drukuje:
źródło
Gdyby nie byli w statycznym bloku inicjującym, gdzie by byli? Jak zadeklarowałbyś zmienną, która miała być lokalna do celów inicjalizacji, i odróżnić ją od pola? Na przykład, w jaki sposób ty chcesz napisać:
Jeśli
first
isecond
nie były w bloku, oni wyglądają jak pola. Gdyby znajdowali się w bloku bezstatic
niego, byłby to liczony jako blok inicjalizacji instancji zamiast statycznego bloku inicjalizacji, więc byłby wykonywany raz dla każdej zbudowanej instancji, a nie w sumie.Teraz w tym konkretnym przypadku możesz zamiast tego użyć metody statycznej:
... ale to nie działa, gdy w tym samym bloku jest wiele zmiennych, które chcesz przypisać, lub nie ma ich wcale (np. jeśli chcesz tylko coś zalogować - lub może zainicjować bibliotekę natywną).
źródło
private static int widgets = 0; static{widgets = 2;}
private static int widgets = 0; static{widgets = 2;}
ustalono, że przypisanie „=” odbywa się w kolejności, co oznacza, że najpierw wstawione zostanie „=”. Powyższy przykład da „widżetom” wartość 2. (PS nie wiedział, że komentarze można edytować tylko w 5 minut ...)Oto przykład:
Kod w sekcji „statycznej” zostanie wykonany w czasie ładowania klasy, przed zbudowaniem jakichkolwiek instancji klasy (oraz przed wywołaniem jakichkolwiek metod statycznych z innego miejsca). W ten sposób możesz upewnić się, że zasoby klasy są gotowe do użycia.
Możliwe jest także zastosowanie statycznych bloków inicjalizacyjnych. Działają one jak rozszerzenia zestawu metod konstruktora zdefiniowanych dla klasy. Wyglądają jak statyczne bloki inicjujące, z wyjątkiem tego, że słowo kluczowe „statyczny” jest pominięte.
źródło
Jest to również przydatne, gdy w rzeczywistości nie chcesz przypisywać wartości do niczego, na przykład ładując jakąś klasę tylko raz w czasie wykonywania.
Na przykład
Hej, jest jeszcze jedna korzyść, możesz jej użyć do obsługi wyjątków. Wyobraź sobie, że
getStuff()
tutaj rzuca coś,Exception
co naprawdę należy do bloku catch:wtedy
static
przydaje się inicjator. Możesz obsłużyć wyjątek tam.Innym przykładem jest robienie rzeczy, których nie można zrobić podczas przypisywania:
Aby wrócić do przykładu sterownika JDBC, każdy przyzwoity sterownik JDBC również korzysta z
static
inicjatora, aby zarejestrować się wDriverManager
. Zobacz także tę i tę odpowiedź.źródło
Powiedziałbym, że
static block
to tylko cukier syntaktyczny. Nic nie można zrobić zstatic
blokiem, a nie z niczym innym.Aby ponownie użyć niektórych przykładów opublikowanych tutaj.
Ten fragment kodu można ponownie napisać bez użycia
static
inicjatora.Metoda nr 1: Z
static
Metoda nr 2: Bez
static
źródło
Istnieje kilka faktycznych powodów, dla których musi istnieć:
static final
członków, których inicjalizacja może zgłosić wyjątekstatic final
elementów z wartościami obliczonymiLudzie zwykle używają
static {}
bloków jako wygodnego sposobu inicjowania rzeczy, od których klasa zależy również w środowisku wykonawczym - takich jak ładowanie określonej klasy (np. Sterowniki JDBC). Można to zrobić na inne sposoby; jednak dwie rzeczy, o których wspomniałem powyżej, można wykonać tylko za pomocą konstrukcji takiej jakstatic {}
blok.źródło
Możesz wykonać bity kodu raz dla klasy, zanim obiekt zostanie skonstruowany w blokach statycznych.
Na przykład
źródło
Powszechnym błędem jest myślenie, że blok statyczny ma dostęp tylko do pól statycznych. W tym celu chciałbym pokazać poniżej fragment kodu, który dość często używam w rzeczywistych projektach (skopiowany częściowo z innej odpowiedzi w nieco innym kontekście):
W tym przypadku inicjalizator służy do utrzymywania indeksu (
ALIAS_MAP
) w celu odwzorowania zestawu aliasów z powrotem na oryginalny typ wyliczenia. Ma to stanowić rozszerzenie wbudowanej metody valueOf dostarczonej przezEnum
siebie.Jak widać, statyczny inicjalizator ma dostęp nawet do
private
polaaliases
. Ważne jest, aby zrozumieć, żestatic
blok ma już dostęp doEnum
instancji wartości (npENGLISH
.). Dzieje się tak, ponieważ kolejność inicjowania i wykonywania w przypadkuEnum
typów , tak jakbystatic private
pola zostały zainicjowane instancjami przedstatic
wywołaniem bloków:Enum
stałe, które są ukryte pola statycznego. Wymaga to konstruktora Enum i bloków instancji, a także inicjalizacji instancji w pierwszej kolejności.static
blok i inicjalizacja pól statycznych w kolejności występowania.static
Należy pamiętać o tej inicjalizacji poza kolejnością (konstruktor przed blokiem). Dzieje się tak również, gdy inicjalizujemy pola statyczne instancjami podobnie jak Singleton (dokonane uproszczenia):Widzimy następujące dane wyjściowe:
Oczywiste jest, że inicjalizacja statyczna może faktycznie nastąpić przed konstruktorem, a nawet po:
Prosty dostęp do Foo w głównej metodzie powoduje załadowanie klasy i rozpoczęcie inicjalizacji statycznej. Ale w ramach inicjalizacji statycznej ponownie wywołujemy konstruktory dla pól statycznych, po czym wznawia się inicjalizację statyczną i kończy konstruktor wywoływany z metody głównej. Raczej złożona sytuacja, w przypadku której mam nadzieję, że przy normalnym kodowaniu nie musielibyśmy się uporać.
Więcej informacji na ten temat można znaleźć w książce „ Skuteczna Java ”.
źródło
aliases
nie oznacza, że blok statyczny może uzyskać dostęp do elementów niestatycznych.aliases
jest dostępny poprzezLanguage
wartości zwracane przezvalues()
metodę / static / . Jak wspominasz, fakt, że zmienne wyliczeniowe są już w tym momencie dostępne, jest niezwykłym bitem - niestatyczne elementy klas regularnych nie byłyby dostępne w tej sytuacji.class Foo { static final Foo Inst1; static final Foo Inst2; static{ Inst1 = new Foo("Inst1"); Inst2 = new Foo("Inst2"); } static { System.out.println("Inst1: " + Inst1.member); System.out.println("Inst2: " + Inst2.member); } private final String member; private Foo(String member){ this.member = member; } }
Powyższy kod nie różni się od przykładu z wyliczeniem i nadal umożliwia dostęp do zmiennej instancji wewnątrz bloku statycznegoEnum
. Jest to najlepszy sposób, aby zagwarantować, że wskazujemy pojedyncze przypadki ”- patrz tutaj . I do twoich punktów, dokonałem kilku aktualizacji.Jeśli zmienne statyczne wymagają ustawienia w czasie wykonywania,
static {...}
blok jest bardzo pomocny.Na przykład, jeśli chcesz ustawić element statyczny na wartość przechowywaną w pliku konfiguracyjnym lub bazie danych.
Przydatne również, gdy chcesz dodać wartości do elementu statycznego,
Map
ponieważ nie możesz dodać tych wartości w początkowej deklaracji elementu.źródło
Masz więc pole statyczne (nazywane jest ono również „zmienną klasy”, ponieważ należy do klasy, a nie do instancji klasy; innymi słowy, jest powiązane z klasą, a nie z jakimkolwiek obiektem) i chcesz ją zainicjować. Jeśli więc NIE chcesz utworzyć wystąpienia tej klasy i chcesz manipulować tym polem statycznym, możesz to zrobić na trzy sposoby:
1- Po prostu zainicjuj go, kiedy deklarujesz zmienną:
2- Mają statyczny blok inicjujący:
3- Mieć metodę klasy (metoda statyczna), która uzyskuje dostęp do zmiennej klasy i inicjuje ją: jest to alternatywa dla powyższego bloku statycznego; możesz napisać prywatną metodę statyczną:
Dlaczego więc miałbyś używać statycznego bloku inicjującego zamiast statycznych metod?
To naprawdę zależy od tego, czego potrzebujesz w swoim programie. Ale musisz wiedzieć, że statyczny blok inicjujący jest wywoływany raz, a jedyną zaletą metody klasowej jest to, że można ją ponownie wykorzystać później, jeśli zajdzie potrzeba ponownego zainicjowania zmiennej klasy.
powiedzmy, że masz złożony program w swoim programie. Inicjujesz go ( na przykład za pomocą pętli for), a następnie wartości w tej tablicy zmienią się w całym programie, ale w pewnym momencie chcesz go ponownie zainicjować (wróć do wartości początkowej). W takim przypadku możesz wywołać prywatną metodę statyczną. Jeśli nie musisz ponownie inicjować wartości w swoim programie, możesz po prostu użyć bloku statycznego i nie potrzebujesz metody statycznej, ponieważ nie będziesz jej później używać w programie.
Uwaga: bloki statyczne są wywoływane w kolejności, w jakiej występują w kodzie.
Przykład 1:
Przykład 2:
źródło
Jako uzupełnienie, jak powiedział @Pointy
Ma się dodać
System.loadLibrary("I_am_native_library")
do bloku statycznego.Zagwarantuje to, że żadna natywna metoda nie zostanie wywołana przed załadowaniem powiązanej biblioteki do pamięci.
Według loadLibrary z Oracle :
Zupełnie więc nieoczekiwanie, umieszczenie System.loadLibrary nie jest używane, aby uniknąć wielokrotnego ładowania biblioteki.
źródło
Najpierw musisz zrozumieć, że same klasy aplikacji są tworzone do
java.class.Class
obiektów podczas działania. To wtedy uruchamiane są bloki statyczne. Więc możesz to zrobić:i wypisałby na konsoli „myInt is 1”. Pamiętaj, że nie utworzyłem żadnej klasy.
źródło
źródło
blok statyczny jest wykorzystywany w każdej technologii do dynamicznego inicjowania elementu danych statycznych, lub możemy powiedzieć, że do dynamicznej inicjalizacji elementu danych statycznych używany jest blok statyczny. Ponieważ do inicjacji elementów statycznych nie mamy, mamy konstruktora, ale nie mamy dowolne miejsce, w którym możemy dynamicznie inicjować element danych statycznych
Teraz moja statyczna int x zainicjuje się dynamicznie .. Boz, gdy kompilator przejdzie do Solution.x, załaduje klasę rozwiązania i ładowanie bloku statycznego w czasie ładowania klasy .. Więc możemy dynamicznie zainicjalizować tego członka danych statycznych ..
}
źródło