Zasadniczo nie używaj niestatycznych bloków inicjalizacyjnych (i być może unikaj również bloków statycznych).
Myląca składnia
Patrząc na to pytanie, istnieją 3 odpowiedzi, ale oszukałeś 4 osoby tą składnią. Byłem jednym z nich i pisałem w Javie od 16 lat! Oczywiście składnia jest potencjalnie podatna na błędy! Trzymałbym się od tego z daleka.
Konstruktory teleskopowe
W przypadku naprawdę prostych rzeczy można użyć konstruktorów „teleskopowych”, aby uniknąć tego zamieszania:
public class Test {
private String something;
// Default constructor does some things
public Test() { doStuff(); }
// Other constructors call the default constructor
public Test(String s) {
this(); // Call default constructor
something = s;
}
}
Wzór konstruktora
Jeśli potrzebujesz doStuff () na końcu każdego konstruktora lub innej zaawansowanej inicjalizacji, być może wzorzec konstruktora byłby najlepszy. Josh Bloch wymienia kilka powodów, dla których budowniczowie są dobrym pomysłem. Konstruktorzy poświęcają trochę czasu na pisanie, ale właściwie napisane, są przyjemnością w użyciu.
public class Test {
// Value can be final (immutable)
private final String something;
// Private constructor.
private Test(String s) { something = s; }
// Static method to get a builder
public static Builder builder() { return new Builder(); }
// builder class accumulates values until a valid Test object can be created.
private static class Builder {
private String tempSomething;
public Builder something(String s) {
tempSomething = s;
return this;
}
// This is our factory method for a Test class.
public Test build() {
Test t = new Test(tempSomething);
// Here we do your extra initialization after the
// Test class has been created.
doStuff();
// Return a valid, potentially immutable Test object.
return t;
}
}
}
// Now you can call:
Test t = Test.builder()
.setString("Utini!")
.build();
Statyczne pętle inicjujące
Często używałem statycznych inicjatorów, ale czasami wpadałem w pętle, w których 2 klasy zależały od siebie nawzajem bloków statycznego inicjatora, zanim klasa mogła zostać w pełni załadowana. Powodowało to „nie udało się załadować klasy” lub podobnie niejasny komunikat o błędzie. Musiałem porównać pliki z ostatnią znaną działającą wersją w kontroli źródła, aby dowiedzieć się, na czym polega problem. W ogóle nie ma zabawy.
Leniwa inicjalizacja
Może statyczne inicjalizatory są dobre ze względu na wydajność, gdy działają i nie są zbyt mylące. Ale ogólnie wolę obecnie leniwe inicjowanie niż statyczne inicjalizatory. Jest jasne, co robią, nie spotkałem się jeszcze z błędem ładowania klas i działają one w większej liczbie sytuacji inicjalizacyjnych niż w blokach inicjujących.
Definicja danych
Zamiast statycznej inicjalizacji do budowania struktur danych (porównaj z przykładami w innych odpowiedziach), teraz używam niezmiennych funkcji pomocniczych definicji danych Paguro :
private ImMap<String,String> days =
map(tup("mon", "monday"),
tup("tue", "tuesday"),
tup("wed", "wednesday"),
tup("thu", "thursday"),
tup("fri", "friday"),
tup("sat", "saturday"),
tup("sun", "sunday"));
Conculsion
Na początku Javy bloki inicjalizacyjne były jedynym sposobem na zrobienie pewnych rzeczy, ale teraz są mylące, podatne na błędy, aw większości przypadków zostały zastąpione lepszymi alternatywami (wyszczególnione powyżej). Interesujące jest wiedzieć o blokach inicjalizujących, na wypadek, gdy zobaczysz je w starszym kodzie lub pojawią się w teście, ale gdybym robił przegląd kodu i widziałem jeden w nowym kodzie, poprosiłbym cię o uzasadnienie, dlaczego żaden z powyższe alternatywy były odpowiednie przed podaniem kciuka do góry.