Statyczny blok inicjalizacji to blok kodu wykonywany przy początkowym ładowaniu klasy JVM przed pierwszym użyciem jakiegokolwiek statycznego członka lub utworzeniem instancji klasy.
Historia pytania:
Java od samego początku oferowała statyczne pola do przechowywania wartości wspólnych dla wszystkich instancji. Wprowadzono bloki static dla niestandardowej inicjalizacji lub złożonych obliczeń podczas uruchamiania klasy.
Problem:
Zwykłe statyczne pola można inicjalizować bezpośrednio podczas deklaracji, ale gdy inicjalizacja jest długotrwała, wymaga dostępu do innych klas/pliku/Bazy Danych lub opiera się na złożonej logice, konieczne jest użycie bloków static. Nieprawidłowe użycie bloków static może prowadzić do nieoczekiwanego zachowania podczas ładowania klas, trudności przy testowaniu, a nawet do deadlocków.
Rozwiązanie:
Bloków static używa się tylko do skomplikowanej inicjalizacji zasobów statycznych, gdy nie można ich wyrazić za pomocą jednego wyrażenia. Dobrym przykładem jest ładowanie sterowników JDBC, odczyt konfiguracji:
public class Config { public static Properties properties; static { properties = new Properties(); try (InputStream in = new FileInputStream("config.properties")) { properties.load(in); } catch (IOException e) { throw new ExceptionInInitializerError(e); } } }
Kluczowe cechy:
Czy można używać return w static bloku?
Nie, operator return jest niedozwolony w blokach static. Można używać throw do wyrzucenia wyjątku.
Kiedy wykonuje się statyczny blok — podczas ładowania klasy czy podczas tworzenia obiektu?
Statyczny blok wykonuje się raz przy ładowaniu klasy, nawet jeśli żaden obiekt nie zostanie utworzony.
Czy mogą być kilka bloków static w jednej klasie? W jakiej kolejności są wykonywane?
Tak, można zadeklarować wiele bloków statycznych. Są one wykonywane w kolejności pojawiania się w kodzie klasy.
W klasie blok static odczytuje duży plik i łączy się z zewnętrzną usługą. W testach lub prostych narzędziach klasa JVM ładowana jest wolno.
Zalety:
Wady:
Blok static sprawdza dostępność licencji oprogramowania przy starcie, wyrzuca ExceptionInInitializerError przy błędzie.
Zalety:
Wady: