Was ist der Unterschied im Speicher zwischen einer Variablen, die null zugewiesen ist, und einer Variablen, die nicht zugewiesen ist?


8

Was ist der Unterschied im Speicher zwischen einer Variablen, die null zugewiesen ist, und einer Variablen, die nicht zugewiesen ist?

Ich weiß, dass es einen Unterschied in der Nutzung gibt, aber was ist der Unterschied im Gedächtnis?


1
Das Teilen Ihrer Forschung hilft allen . Sagen Sie uns, was Sie versucht haben und warum es Ihren Anforderungen nicht entsprach. Dies zeigt, dass Sie sich die Zeit genommen haben, um sich selbst zu helfen, es erspart uns, offensichtliche Antworten zu wiederholen, und vor allem hilft es Ihnen, eine spezifischere und relevantere Antwort zu erhalten. Siehe auch Fragen
Mücke

Antworten:


11

Es gibt keinen Unterschied zwischen den beiden "im Speicher".

Aus der Java-Sprachspezifikation, 4.12.5. Anfangswerte von Variablen :

Jede Variable in einem Programm muss einen Wert haben, bevor ihr Wert verwendet wird:

  • Jede Klassenvariable, Instanzvariable oder Array-Komponente wird beim Erstellen mit einem Standardwert initialisiert (§15.9, §15.10.2):

...

    • Für alle Referenztypen (§4.3) ist der Standardwert null.

...

    • Eine lokale Variable (§14.4, §14.14) muss explizit einen Wert erhalten, bevor sie entweder durch Initialisierung (§14.4) oder Zuweisung (§15.26) auf eine Weise verwendet wird, die anhand der Regeln für die bestimmte Zuweisung (§14.26) überprüft werden kann 16 (definitive Zuordnung)).

Referenzvariablen auf Klassen- oder Objektebene wird ein Nullwert zugewiesen.

Referenzvariablen auf Methodenebene (Stapelebene) haben einen nicht angegebenen Wert (unter Verwendung des C ++ - Begriffs). In der Praxis ist dies häufig null, aber der Standard gibt nicht an, was in der Referenzvariablen enthalten ist, sondern nur, dass sie vor der Verwendung zugewiesen werden muss. Die Verwendung einer Referenzvariablen auf dem Stapel auf eine andere Weise als die Zuweisung als erste Verwendung führt zu einem Kompilierungsfehler.


Wenn Sie eine Variable deklarieren, ohne sie auf null zu initialisieren, und sie dann innerhalb eines if-thenBlocks initialisieren , teilt Ihnen der Compiler mit, dass die Variable im Code möglicherweise nicht initialisiert ist, wenn der thenBlock nicht ausgeführt wird. Wenn Sie es initialisieren, nullkompiliert der Code. Warum ist das so, dass "eine Referenz, der nicht explizit ein Wert zugewiesen wurde, den Wert null hat" ?
Tulains Córdova

@Snowman Ist das nicht ein Implementierungsdetail? Nur Klassenvariablen, Instanzvariablen und Array-Komponenten müssen auf ihre Standardwerte initialisiert werden. Lokale Variablen sind nicht erforderlich, und Sie können sie nicht verwenden, bevor sie initialisiert wurden. Wenn Sie sich eine nicht initialisierte lokale Variable im Speicher ansehen, sehen Sie, was auch immer die Implementierung damit zu tun hat, was möglicherweise keine Initialisierung erfordert, nullda dies unnötige Arbeit wäre.
Doval

@Snowman - Da es illegal ist, einen lokalen Prior zu verwenden, bevor ihm ein Wert zugewiesen wird, ist es ein Implementierungsdetail, ob einer nicht initialisierten lokalen Variablen ein Anfangswert zugewiesen wird.
David Hammen

1
Bitte beachten Sie meine letzte Bearbeitung. Ich beschuldige einen unzureichenden Kaffee an einem Montagmorgen.

4

Was ist der Unterschied zwischen einer Variablen, die null zugewiesen ist, und anderen Variablen, die nicht im Speicher zugewiesen sind?

In Java gibt es keine nicht zugewiesene Variable. Klassendatenelementen, die keine explizite Zuweisung haben, wird der Standardwert für den Typ, null für ein Objekt oder 0 für primitive Typen zugewiesen.

Lokale Variablen befinden sich auf dem Stapel. (Nicht-primitive Einheimische, wie sie MyType fooauch als Referenz auf dem Stapel leben.) Die Stapelzuordnung ist einfach. Wenn ein Block Deklarationen für lokale Variablen enthält, wird der von diesen lokalen Variablen benötigte Speicherplatz auf dem Stapel reserviert. Es ist unerheblich, ob diesen lokalen Variablen beim Anpassen des Stapels Werte zugewiesen werden, um diese lokalen Variablen aufzunehmen.

Es spielt keine Rolle, ob lokalen Variablen zum Zeitpunkt der Ausführung des Blocks ein Wert zugewiesen wird oder nicht. Ein Grund ist, dass sich die benötigte Größe nicht ändert. Grundelemente haben eine feste Größe, und Nicht-Grundelemente sind tatsächlich Referenzen. (Das referenzierte Objekt befindet sich auf dem Heap und nicht auf dem Stapel.) Der zweite Grund ist, dass die Verwendung einer lokalen Variablen, der kein Wert zugewiesen wurde, ein Kompilierungsfehler ist. Dies überlässt es der Java-Laufzeit, einer deklarierten, aber nicht zugewiesenen lokalen Variablen einen Wert (nicht unbedingt den Standardwert) zuzuweisen.


Irgendwo in Ihrer Antwort finden Sie die Erklärung dazu: Wenn Sie eine Variable deklarieren, ohne sie auf null zu initialisieren, und sie dann innerhalb eines if-thenBlocks initialisieren , teilt Ihnen der Compiler mit, dass die Variable im Code möglicherweise nicht initialisiert ist, wenn der thenBlock nicht ausgeführt wird. Wenn Sie es initialisieren, nullkompiliert der Code. Warum ist das so, dass "eine Referenz, der nicht explizit ein Wert zugewiesen wurde, den Wert null hat" ? Aber es ist mir immer noch nicht klar genug. Könnten Sie es mit anderen Worten erklären?
Tulains Córdova

2
Lokale Variablen müssen keinen Anfangswert erhalten. Ihnen muss vor der ersten Verwendung ein Wert zugewiesen werden. Ob der dieser Variablen zugeordnete Speicher auch bei einer Deklaration ohne Zuweisung einen expliziten Anfangswert erhält, ist ein Implementierungsdetail. Der Speicher ist vorhanden (so funktionieren Stapel), aber dieser Speicherplatz kann vor dem Anpassen des Stapels mit allem gefüllt bleiben, was sich gerade in diesem Speicher befindet.
David Hammen

@ user61852 - Dass eine Referenz, der kein Wert explizit zugewiesen wurde, den Wert null hat, gilt für Klassenmitglieder, jedoch nicht unbedingt für lokale Variablen. Wenn Sie Ihren Code mit aktiviertem Debug kompilieren, initialisiert der Compiler mit ziemlicher Sicherheit Ihre nicht initialisierten nicht-primitiven lokalen Variablen auf null. Dies vereinfacht die Entwicklung des Java-Debuggers erheblich. Aber was ist, wenn Sie mit deaktiviertem Debug kompilieren? Jetzt ist diese Initialisierung unnötige zusätzliche Arbeit. Was sich in diesem Speicher befindet, ist irrelevant, da bekannt ist, dass der Speicher bei der ersten Verwendung einen gültigen Wert enthält.
David Hammen

Aus Bytecode-Sicht werden lokale Variablen auf dem Stapel zugewiesen. Der JITter kann jedoch entscheiden, dass ein bestimmter Stapeleintrag nicht tatsächlich auf dem Stapel gespeichert werden soll, sondern dass das Speichern und Laden von diesem Eintrag auf ein bestimmtes CPU-Register gerichtet werden soll. Wenn der JITter feststellt, dass ein Stapeleintrag nach Erreichen eines bestimmten Punkts nicht mehr gelesen werden kann, ohne neu geschrieben worden zu sein, kann er das zugehörige Register dieses Eintrags für einen anderen Zweck neu zuweisen.
Supercat

1

Erstens müssen Sie sich wirklich keine Gedanken über den von lokalen Variablen verwendeten Speicherplatz machen. In einer Zeile kann ich ein Array von 100.000 Ganzzahlen zuweisen, das mehr Platz beansprucht als alle lokalen Variablen, die Sie jemals verwenden werden.

Zweitens wird Ihr Code von einem Compiler kompiliert, der wahrscheinlich clever ist. Wenn Ihre Variable nicht initialisiert ist, wird sie nicht verwendet (da der Compiler die Verwendung nicht initialisierter Variablen nicht zulässt). Aber wenn Sie es auf Null initialisieren, wird es immer noch nicht verwendet! Der Compiler wird leicht herausfinden, dass er nicht verwendet wird und überhaupt keinen Platz für die Variable verwendet. Selbst wenn es verwendet wird, kann der Compiler leicht herausfinden, dass der Wert Null ist, und anstelle der Variablen Null verwenden.

Aber drittens sind dies alles Mikrooptimierungen, die Ihnen in keiner Weise helfen werden, ein Programm zu optimieren. Sie versuchen, vier oder acht Bytes zu speichern. Konzentrieren Sie sich auf das Speichern von Megabyte, wenn Sie etwas speichern möchten.

Und während einige Leute behaupten, Variablen sollten immer initialisiert werden, trifft dies in Java nicht zu. Sie sollten eine Variable immer nur auf einen aussagekräftigen Wert setzen. Angenommen, Sie möchten eine Variable auf den Namen einer Person setzen und vergessen, dies in einem Codepfad zu tun. Wenn Sie die Variable blind auf Null initialisieren, kann der Compiler Ihnen dies nicht mitteilen. Ohne die Initialisierung kann und wird der Compiler Sie über Ihren Fehler informieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.