Instanziierung mehrerer gleicher Objekte

8

Was genau passiert in Java, wenn Sie dasselbe Objekt mehrmals instanziieren?

Zum Beispiel:

Test test = new Test();

dann später werde ich es wieder aufrufen, Test test = new Test();wieder oder innerhalb einer Schleife. Wird die vorherige Instanziierung entsorgt?

userIsAMonkey
quelle

Antworten:

16
  1. Jeder Aufruf new Test()erstellt eine neue Objektinstanz der TestKlasse
  2. test = new Test();weist der Variablen eine Referenz dieses Objekts zutest
  3. Eine wiederholte Anweisung test = new Test()erstellt eine zweite Instanz von Testund weist die Variable testerneut der Variablen zu, sodass die erste Referenz ersetzt wird.

Ob und wann die erste Instanziierung erfolgt, hängt jedoch davon ab. In der Java-Laufzeitumgebung werden Verweise nachverfolgt. Solange Verweise auf ein verwendetes Objekt vorhanden sind, wird das Objekt nicht entsorgt. Wenn beispielsweise zwischen Schritt 2 und Schritt 3 die Referenz auf die erste Instanziierung an einer anderen Stelle (wie Test test2 = test;) gespeichert ist und diese Variable zum Zeitpunkt des Auftretens von Schritt 3 noch im Gültigkeitsbereich liegt, wird das erste Objekt nicht entsorgt, da test2es immer noch eine Referenz enthält dazu. Wenn es jedoch keine solche Anweisung gibt und in Schritt 3 die einzige Referenz auf das erste Objekt weggelassen wird, erfolgt eine Entsorgung dieses Objekts.

Beachten Sie, dass die Entsorgung selbst nicht sofort erfolgt, sondern manchmal später, wenn der Garbage Collector das nächste Mal ausgeführt wird. Dies ist jedoch unabhängig von der Semantik des diskutierten Codes, das ist nur eine Frage des Gedächtnisses und der Leistung.

Doc Brown
quelle
4
Die JVM führt keine Referenzzählung durch. Genau genommen schreibt die Spezifikation nicht vor, wie (oder sogar diese) Garbage Collection implementiert wird, aber alle gängigen JVMs verwenden eine Art Tracing-Collector.
Michael Borgwardt
@ MichaelBorgwardt: Meine Antwort wurde aufgrund Ihres Kommentars geändert.
Doc Brown
if between step 2 and step 3 the reference to the first instantiation is stored somewhere else (like Test test2 = test;), and that variable is still in scope when step 3 occurs...Dies ist etwas umständlich, aber die Speicherbereinigung basiert nicht auf dem Umfang, sondern auf der Erreichbarkeit. Es ist möglich, dass sich eine Variable im Gültigkeitsbereich befindet, ihr Wert jedoch nicht mehr verwendet wird und dieser Wert durch Müll gesammelt werden kann. Müllsammler haben keine Möglichkeiten, Entscheidungen auf dieser Grundlage zu treffen.
Doval
@Doval: Ich stimme zu, dieser Kommentar ist pedantisch ;-)
Doc Brown
5

1: Einige Formulierungen: Wir instanziieren überhaupt keine Objekte, wir instanziieren Klassen und das Produkt einer Klasseninstanziierung ist ein Objekt (auch als Instanz bezeichnet). Natürlich können wir eine Klasse so oft instanziieren, wie erforderlich, um mit jeder Instanziierung ein neues und anderes Objekt zu erstellen.

2: Wie auch immer, Sie können den von Ihnen vorgeschlagenen Code nicht haben:

Test test = new Test();
Test test = new Test();

Sie können dies auch nicht haben:

for (i=0; i<3; i++) {
    Test test = new Test();
    Test test = new Test();
}

Keiner wird kompiliert, da der Teil Test testdie Deklaration einer Variablen test(vom Typ Test) ist und keine Sprache, einschließlich Java, die Deklaration der gleichen Variablen im selben Bereich ermöglicht.

Sie können jedoch dieselbe Variable (wie der Name schon sagt) mehrfach mit unterschiedlichen Objekten wie folgt zuweisen:

Test test = new Test();
test = new Test();

In der ersten Zeile testwird ein neu erstelltes Objekt deklariert und zugewiesen. Die zweite Zeile wird einem testanderen Objekt zugewiesen , das ebenfalls neu erstellt wurde.

Beachten Sie auch, dass Verknüpfungen in Java zulässig sind:

for (i=0; i<3; i++) {
    Test test = new Test();
}

Diese Schleife wird nicht testdreimal deklariert . Es versteht sich, der Variablen drei neue verschiedene Objekte nacheinander zuzuweisen, testdie nur einmal deklariert werden. (Vergleiche mit der vorherigen Schleife).

3: Was passiert mit der Variablen testund den beiden Typobjekten Test?

Der Variablen testwird zuerst die Referenz eines Objekts und dann eines anderen Objekts zugewiesen. Eine Variable behält nur die zuletzt zugewiesene Referenz bei.

Das erste Objekt des Typs Testist nicht testmehr zugeordnet. Wenn keiner anderen Variablen ihre Referenz zugewiesen wurde, kann das Programm in keiner Weise auf dieses Objekt zugreifen und ist daher unbrauchbar. Es wird vom System zur Speicherbereinigung berechtigt. Irgendwann wird das System (die JVM) seinen Garbage Collector ausführen, wodurch er aus dem Speicher gelöscht wird.

Das zweite Objekt wird so lange leben, wie mindestens eine Variable darauf verweist. Der Garbage Collector kümmert sich ebenfalls darum und bringt es zum Friedhof für nicht referenzierte Objekte. Das ist das wahre Leben von Java-Objekten :-(

min
quelle
Ich habe diesen Fehler zufällig in einer Klasse gefunden. Die Klassen haben eine Eigenschaft, die wie folgt deklariert ist: WindowManager wm = new WindowsManager (); und dann eine Methode, bei der der Programmierer diese Eigenschaft verwendete, aber fälschlicherweise schrieb: WindowManager wm = new WindowsManager (); nochmal. Es wird nicht nur kompiliert, sondern auch ausgeführt !! Keine Warnung und natürlich funktionierte die Anwendung, die ein Test ist, nicht gut. Dann wurde mir klar, dass das Objekt innerhalb des Methodenbereichs erstellt wurde und die Eigenschaft nie geändert wurde. Also sei vorsichtig
Ricker Silva
1
Wie Sie perfekt erklärt haben, ist dies keine Neuzuweisung derselben Variablen. Ein ähnlicher Shadowing-Fehler kann bei der Verwendung eines Parameters auftreten, wenn Sie das thisSchlüsselwort vergessen , wie in Konstruktoren : this.name = name.
Minuten
-1

Kurze Antwort: Alle zuvor erstellten Objekte werden entsorgt, wenn niemand auf sie zeigt. Es wird nur die neueste Version vorhanden sein, da der Test darauf verweist.

Tulains Córdova
quelle