Verwenden Sie im Allgemeinen keine nicht statischen Initialisierungsblöcke (und vermeiden Sie möglicherweise auch statische).
Verwirrende Syntax
Wenn Sie sich diese Frage ansehen, gibt es 3 Antworten, aber Sie haben 4 Personen mit dieser Syntax getäuscht. Ich war einer von ihnen und schreibe seit 16 Jahren Java! Natürlich ist die Syntax möglicherweise fehleranfällig! Ich würde mich davon fernhalten.
Teleskopbauer
Für wirklich einfache Dinge können Sie "teleskopierende" Konstruktoren verwenden, um diese Verwirrung zu vermeiden:
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;
}
}
Builder-Muster
Wenn Sie doStuff () am Ende eines jeden Konstruktors oder einer anderen raffinierten Initialisierung benötigen, ist möglicherweise ein Builder-Muster am besten geeignet. Josh Bloch nennt mehrere Gründe, warum Bauherren eine gute Idee sind. Bauherren nehmen sich etwas Zeit zum Schreiben, aber richtig geschrieben ist es eine Freude, sie zu benutzen.
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();
Statische Initialisierungsschleifen
Früher habe ich häufig statische Initialisierer verwendet, aber gelegentlich kam es zu Schleifen, in denen zwei Klassen davon abhingen, ob die statischen Initialisiererblöcke des jeweils anderen aufgerufen wurden, bevor die Klasse vollständig geladen werden konnte. Dies erzeugte eine "Klasse konnte nicht geladen werden" oder eine ähnlich vage Fehlermeldung. Ich musste Dateien mit der letzten bekannten Arbeitsversion in der Quellcodeverwaltung vergleichen, um herauszufinden, wo das Problem lag. Gar kein Spaß.
Lazy Initialization
Vielleicht sind statische Initialisierer aus Performancegründen gut, wenn sie funktionieren und nicht zu verwirrend. Aber im Allgemeinen bevorzuge ich in diesen Tagen die verzögerte Initialisierung gegenüber statischen Initialisierern. Es ist klar, was sie tun, ich habe noch keinen Fehler beim Laden von Klassen mit ihnen entdeckt, und sie funktionieren in mehr Initialisierungssituationen als Initialisierungsblöcke.
Datendefinition
Anstelle der statischen Initialisierung zum Erstellen von Datenstrukturen (vergleiche die Beispiele in den anderen Antworten) verwende ich jetzt die unveränderlichen Hilfefunktionen für die Datendefinition von 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"));
Erschütterung
Zu Beginn von Java waren Initialisierungsblöcke die einzige Möglichkeit, einige Dinge zu tun, aber jetzt sind sie verwirrend, fehleranfällig und wurden in den meisten Fällen durch bessere Alternativen ersetzt (siehe oben). Es ist interessant, Informationen zu Initialisierungsblöcken zu erhalten, falls Sie sie im Legacy-Code sehen oder wenn sie in einem Test auftauchen. Wenn ich jedoch eine Codeüberprüfung durchführe und einen neuen Code sehe, möchte ich Sie bitten, zu begründen, warum keiner der Blöcke vorhanden ist Die oben genannten Alternativen waren geeignet, bevor Sie Ihrem Code die Daumen hoch gaben.