114 Stimmen

Warum werden lokale Variablen in Java nicht initialisiert?

Gab es einen Grund, warum die Entwickler von Java der Meinung waren, dass lokalen Variablen kein Standardwert zugewiesen werden sollte? Im Ernst: Wenn Instanzvariablen ein Standardwert zugewiesen werden kann, warum können wir das dann nicht auch für lokale Variablen tun?

Und es führt auch zu Problemen, wie in dieser Kommentar zu einem Blogeintrag :

Nun, diese Regel ist sehr frustrierend, wenn man versucht, eine Ressource in einem Endblock zu schließen. Wenn ich die Ressource innerhalb eines Try-Blocks instanziiere, aber versuche, sie innerhalb des Finally-Blocks zu schließen, erhalte ich diesen Fehler. Wenn ich die Instanziierung außerhalb des Try-Blocks verschiebe, erhalte ich eine weitere Fehlermeldung, die besagt, dass die Instanziierung innerhalb eines Try-Blocks erfolgen muss.

Sehr frustrierend.

1voto

kaya3 Punkte 40309

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.

0voto

David Santamaria Punkte 8411

Die lokalen Variablen werden auf einem Stack gespeichert, aber die Instanzvariablen werden auf dem Heap gespeichert, so dass die Möglichkeit besteht, dass ein früherer Wert auf dem Stack anstelle eines Standardwerts gelesen wird, wie es auf dem Heap geschieht.

Aus diesem Grund erlaubt es die JVM nicht, eine lokale Variable zu verwenden, ohne sie zu initialisieren.

0voto

Kezzer Punkte 17570

Eclipse gibt sogar Warnungen vor nicht initialisierten Variablen aus, so dass es ohnehin ziemlich offensichtlich ist. Ich persönlich finde es gut, dass dies das Standardverhalten ist, denn sonst könnte Ihre Anwendung unerwartete Werte verwenden, und anstatt dass der Compiler einen Fehler meldet, tut er gar nichts (sondern gibt vielleicht eine Warnung aus), und dann werden Sie sich den Kopf darüber zerbrechen, warum sich bestimmte Dinge nicht so verhalten, wie sie sollten.

0voto

htlbydgod Punkte 133

Die Instanzvariablen haben Standardwerte, aber die lokalen Variablen können keine Standardwerte haben. Da lokale Variablen grundsätzlich in Methoden/Verhaltensweisen enthalten sind, besteht ihr Hauptziel darin, einige Operationen oder Berechnungen durchzuführen. Daher ist es keine gute Idee, Standardwerte für lokale Variablen festzulegen. Andernfalls ist es sehr schwierig und zeitaufwändig, die Gründe für unerwartete Antworten zu überprüfen.

0voto

Ankit Mittal Punkte 1

Der Speicherstapel für Methoden wird zur Ausführungszeit erstellt. Die Reihenfolge der Methodenstapel wird zur Ausführungszeit festgelegt.

Es könnte eine Funktion geben, die gar nicht aufgerufen werden darf. Die Instanziierung lokaler Variablen zum Zeitpunkt der Objektinstanziierung wäre also eine völlige Verschwendung von Speicher. Außerdem verbleiben Objektvariablen während des gesamten Objektlebenszyklus einer Klasse im Speicher, während lokale Variablen und ihre Werte für die Garbage Collection in Frage kommen, sobald sie aus dem Speicherstapel entfernt werden.

Es wäre also völlig unlogisch und speicherverschwendend, den Variablen von Methoden Speicherplatz zuzuweisen, die möglicherweise gar nicht aufgerufen werden oder, selbst wenn sie aufgerufen werden, während des Lebenszyklus eines Objekts nicht im Speicher bleiben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X