2015-06-17 12 views
5

Meine Frage bezieht sich auf:Lebenszyklus eines neuen Objekts ohne Bezug

Was tatsächlich passiert, wenn wir so etwas in unserem Code haben:

(new SomeClass()).longMethod(); 

Gibt es noch eine Art von unbenannte (stark?) Verweis verweist auf das neu erstellte Objekt auf Heap Stack?

Wenn sich nichts auf Stack befindet, wie kann Garbage Collector das Objekt für die Dauer der Methode beibehalten?

Ist es vielleicht die gleiche wie

{ 
    // very local scope 
    SomeClass throwAwayRef = new SomeClass(); 
    throwAwayRef.longMethod(); 
} 
+0

Schon gehört von 'this'? – Ingo

+0

@Ingo - Pflege um zu erarbeiten? –

+0

Antwort zuerst. Was ist das in einer Methode? Und woher kommt es? – Ingo

Antwort

1

Ja, Verweis auf das neue Objekt auf dem Stapel vorhanden ist.

direkt aus Oracle:

Um ein Feld zuzugreifen, können Sie einen benannten Verweis auf ein Objekt verwenden, wie in die vorherigen Beispiele, oder Sie können einen beliebigen Ausdruck verwenden, die eine Objektverweis zurückgibt. Erinnern Sie sich, dass der neue Operator einen Verweis auf ein Objekt zurückgibt. So könnte man den Wert von neuen zurückgegeben verwenden, um ein Felder der neuen Objekts zuzugreifen:

int height = new Rectangle().height;

Diese Anweisung erstellt ein neues Rectangle-Objekt und erhält sofort seine Höhe. Im Wesentlichen berechnet die -Anweisung die Standardhöhe eines Rectangle. Beachten Sie, dass , nachdem diese Anweisung ausgeführt wurde, das Programm nicht mehr über einen Verweis auf das erstellte Rectangle verfügt, da das Programm nie die Referenz irgendwo gespeichert hat. Das Objekt ist nicht referenziert und seine Ressourcen können von der Java Virtual Machine wiederverwendet werden.

Quelle: https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html

+3

mehr Beweis oder ein Beispiel bitte – jgr208

+0

Die Höhenmethode könnte 'this' irgendwo speichern, also ist Oracle hier nicht ganz richtig. Ohne den Höhencode zu kennen, wissen wir einfach nicht, ob die Referenz irgendwo gespeichert ist. – Ingo

+0

@Ingo Nun, ich nehme an, sie meinten 'java.awt.Rectangle', das dieses Verhalten nicht hat, aber Sie machen einen guten Punkt für den allgemeinen Fall. –

3

Ja,

new SomeClass().longMethod(); 

effektiv ist die gleiche wie vor allem von einem Garbage Collection Standpunkt:

{ 
    SomeClass throwAwayRef = new SomeClass(); 
    throwAwayRef.longMethod(); 
} 

Die in-line eine Version hat impliziter Verweis auf das neue Objekt (auf dem Stapel). Sobald der Methodenaufruf beendet ist, wird er für die Garbage Collection verfügbar.

+0

Beachten Sie, dass die beiden Snippets auf der Bytecodeebene unterschiedlich sind, obwohl sie tatsächlich funktional äquivalent sind. – arshajii

+0

Ist es irgendwo dokumentiert oder wird JVM-Implementierungen überlassen? –

5

Sie können an der Bytecode für Einsicht aussehen:

0: new   #16     // class SomeClass 
    3: dup 
    4: invokespecial #18     // Method SomeClass."<init>":()V 
    7: invokevirtual #19     // Method SomeClass.longMethod:()V 
  • new ordnet das Objekt tatsächlich auf eine Referenz, die auf den Stapel geschoben wird.
  • dup verdoppelt den oberen Stapel; Jetzt sind die obersten zwei Stapelelemente Verweise auf das neu erstellte Objekt.
  • invokespecial ruft hier den Konstruktor SomeClass auf, den Stapel knallend; Jetzt besteht der Stapel aus nur einer einzigen Referenz auf unsere SomeClass Instanz. Die Instanz ist nicht GCed, da auf dem Stapel ein Verweis darauf existiert.
  • invokevirtual hier ruft longMethod. Auch hier ist die Instanz nicht GCed, da ein Verweis darauf immer noch auf dem Stapel vorhanden ist (und nach dem Abschluss der Methode abgerufen wird. Danach ist sie ist für GC geeignet).

(new SomeClass()).longMethod(); 

ist nicht dasselbe wie

{ 
    // very local scope 
    SomeClass throwAwayRef = new SomeClass(); 
    throwAwayRef.longMethod(); 
} 

im Bytecode-Ebene, da letztere eine astore und eine aload beinhaltet. Allerdings sind die beiden sicherlich funktional gleichwertig. Die SomeClass-Instanz wird weiterhin für GC zugelassen, nachdem longMethod abgeschlossen wurde (die Stapel für die beiden Snippets sehen identisch aus, wenn invokevirtual ausgeführt wird).


Referenz:

Verwandte Themen