W Javie bloki inicjalizacji (init-bloki) to specjalne bloki kodu, które są wykonywane podczas tworzenia instancji obiektu klasy, ale przed wywołaniem konstruktora. Istnieją dwa rodzaje:
public class Example { static { System.out.println("Blok statyczny"); } { System.out.println("Blok instancji"); } public Example() { System.out.println("Konstruktor"); } }
Przy tworzeniu nowego obiektu zostanie wyświetlone:
Blok statyczny
Blok instancji
Konstruktor
Używanie init-bloków ma sens, gdy potrzebna jest wspólna logika dla wszystkich konstruktorów lub złożona inicjalizacja, która nie mieści się w deklaracji zmiennej. Jednak najczęściej preferowane są konstruktory.
Pytanie: W jakiej kolejności inicjalizowane są pola, bloki static, bloki instance i konstruktory przy tworzeniu obiektu?
Odpowiedź:
Historia
W dużym projekcie wystąpił problem z inicjalizacją: jeden z programistów przenosił wspólną logikę z konstruktora do init-bloku, nie uwzględniając kolejności wywołań. W rezultacie niektóre pola nie zostały prawidłowo zainicjalizowane przed uruchomieniem logiki, co spowodowało NullPointerException podczas tworzenia obiektu.
Historia
Ponowne użycie dużego init-bloku w klasie abstrakcyjnej, od której dziedziczyły inne klasy, doprowadziło do tego, że podklasy nie nadpisywały porządku inicjalizacji odpowiednio. Spowodowało to nieoczekiwane zachowanie podczas dziedziczenia i błędy związane z kolejnością wywoływania init-bloków i konstruktorów.
Historia
Programista założył, że pola statyczne mogą być ponownie inicjalizowane przy każdym nowym tworzeniu obiektu i dodał do bloku static logikę czyszczenia zasobów. Doprowadziło to do tego, że zasoby były czyszczone tylko raz przy ładowaniu klasy, a wszelkie późniejsze zarządzanie pamięcią „odpadło”. Ponieważ blok static jest wywoływany tylko jednokrotnie, doprowadziło to do wycieków pamięci i niewłaściwego zarządzania zasobami.