2015-06-17 16 views
5

La mia domanda è legata a:vita di un nuovo oggetto senza riferimento

Quello che succede in realtà quando abbiamo qualcosa di simile nel nostro codice:

(new SomeClass()).longMethod(); 

C'è ancora una specie di riferimento senza nome (forte?) che punta all'oggetto appena creato su Heap put on Stack?

Se nulla è in Stack, come si riconosce Garbage Collector per conservare l'oggetto per la durata del metodo?

E 'forse la stessa di

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

mai sentito parlare di 'this'? – Ingo

+0

@Ingo - Cura di elaborare? –

+0

Rispondi per primo. Cosa c'è in un metodo? E da dove viene? – Ingo

risposta

1

Sì, riferimento al nuovo oggetto esiste in pila.

direttamente da Oracle:

Per accedere a un campo, è possibile utilizzare un riferimento di nome a un oggetto, come in esempi precedenti, oppure è possibile utilizzare qualsiasi espressione che restituisce un riferimento oggetto. Ricordiamo che il nuovo operatore restituisce un riferimento a un oggetto. Così si potrebbe utilizzare il valore restituito dal nuovo di accedere ai campi di un nuovo oggetto :

int height = new Rectangle().height;

Questa istruzione crea un nuovo rettangolo oggetto e subito ottiene la sua altezza. In sostanza, l'istruzione calcola l'altezza predefinita di un rettangolo. Si noti che dopo che questa istruzione è stata eseguita, il programma non ha più un riferimento al rettangolo creato, perché il programma non ha mai memorizzato il riferimento in nessun punto. L'oggetto non è referenziato e le sue risorse sono gratuite per essere riciclate dalla Java Virtual Machine.

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

+3

più prova o un esempio per favore – jgr208

+0

Il metodo di altezza potrebbe memorizzare "questo" da qualche parte, quindi Oracle non è proprio qui. Senza conoscere il codice di altezza, non sappiamo se il riferimento è memorizzato da qualche parte. – Ingo

+0

@Ingo Beh, sto assumendo che intendessero 'java.awt.Rectangle', che non ha questo comportamento, ma tu fai un buon punto per il caso generale. –

3

Sì,

new SomeClass().longMethod(); 

è effettivamente la stessa, soprattutto dal punto di vista garbage collection:

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

L'in-line versione ha un riferimento implicito al nuovo oggetto (in pila). Diventa disponibile per la raccolta dei rifiuti non appena termina la chiamata al metodo.

+0

Si noti che i due snippet sono diversi a livello di bytecode, sebbene siano effettivamente equivalenti dal punto di vista funzionale. – arshajii

+0

È documentato da qualche parte o lasciato alle implementazioni JVM? –

5

Potete guardare il bytecode per intuizione:

0: new   #16     // class SomeClass 
    3: dup 
    4: invokespecial #18     // Method SomeClass."<init>":()V 
    7: invokevirtual #19     // Method SomeClass.longMethod:()V 
  • new assegna in realtà l'oggetto, un riferimento al quale viene spinto in pila.
  • dup duplica la parte superiore dello stack; ora i primi due elementi dello stack sono riferimenti all'oggetto appena creato.
  • invokespecial qui chiama il costruttore di SomeClass, apre lo stack; ora lo stack consiste in un solo riferimento alla nostra istanza SomeClass. L'istanza non è GC in quanto esiste un riferimento allo stack.
  • invokevirtual qui chiama longMethod. Anche in questo caso, l'istanza non è GCed perché esiste ancora un riferimento allo stack (e viene scoppiato dopo il completamento del metodo, dopo di che è è idoneo per GC).

(new SomeClass()).longMethod(); 

non è la stessa

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

a livello bytecode, in quanto quest'ultima comporta un astore e un aload. Tuttavia, i due sono certamente equivalenti dal punto di vista funzionale. L'istanza SomeClass diventa ancora valida per GC dopo che longMethod è stato completato (le pile per i due frammenti saranno identiche quando viene eseguito invokevirtual).


Riferimento: