Drehen Sie das um und fragen Sie: Warum werden Felder mit Standardwerten initialisiert? Wenn der Java-Compiler von Ihnen verlangen würde, Felder selbst zu initialisieren, anstatt ihre Standardwerte zu verwenden, wäre das effizienter, weil der Speicher vor der Verwendung nicht auf Null gesetzt werden müsste. Es wäre also ein sinnvolles Sprachdesign, wenn todo Variablen wurden in dieser Hinsicht wie lokale Variablen behandelt.
Der Grund dafür ist nicht, dass es schwieriger ist, dies für Felder zu überprüfen als für lokale Variablen. Der Java-Compiler weiß bereits, wie er prüfen kann, ob ein Feld definitiv von einem Konstruktor initialisiert wird, denn er muss dies für final
Felder. Es wäre also nur wenig zusätzliche Arbeit für den Compiler, die gleiche Logik auf andere Felder anzuwenden, um sicherzustellen, dass sie im Konstruktor definitiv zugewiesen werden.
Der Grund dafür ist, dass selbst für final
Bei Feldern, bei denen der Compiler nachweist, dass das Feld im Konstruktor definitiv zugewiesen wird, kann sein Wert vor der Zuweisung noch aus anderem Code ersichtlich sein:
class A {
final int x;
A() {
this.x = calculate();
}
int calculate() {
System.out.println(this.x);
return 1;
}
}
In diesem Code ordnet der Konstruktor definitiv der this.x
aber selbst dann ist der Standardwert für das Feld von 0
ist sichtbar in der calculate
Methode an der Stelle, an der this.x
gedruckt wird. Wenn das Feld vor dem Aufruf des Konstruktors nicht auf Null gesetzt wurde, dann wird die calculate
Methode wäre in der Lage, den Inhalt des nicht initialisierten Speichers zu beobachten, was ein nicht-deterministisches Verhalten wäre und potenzielle Sicherheitsbedenken aufwerfen würde.
Die Alternative wäre, den Aufruf der Methode zu verbieten calculate()
an dieser Stelle des Codes, an der das Feld noch nicht endgültig zugewiesen ist. Aber das wäre unpraktisch; es ist nützlich, Methoden aus dem Konstruktor auf diese Weise aufrufen zu können. Die Bequemlichkeit, dies tun zu können, ist mehr wert als der winzige Leistungsverlust, der dadurch entsteht, dass der Speicher für die Felder vor dem Aufruf des Konstruktors auf Null gesetzt wird.
Beachten Sie, dass diese Argumentation nicht für lokale Variablen gilt, da die nicht initialisierten lokalen Variablen einer Methode für andere Methoden nicht sichtbar sind, da sie lokal sind.