77

Qualcuno può spiegare la differenza tra le tre classi di riferimento (o pubblicare un collegamento a una bella spiegazione)? SoftReference>WeakReference>PhantomReference, ma quando dovrei usare ciascuno di essi? Perché c'è un WeakHashMap ma non lo SoftHashMap o PhantomHashMap?Comprendere le classi di riferimento di Java: SoftReference, WeakReference e PhantomReference

E se uso il seguente codice ...

WeakReference<String> ref = new WeakReference<String>("Hello!"); 
if (ref != null) {     // ref can get collected at any time... 
    System.gc();     // Let's assume ref gets collected here. 
    System.out.println(ref.get()); // Now what?! 
} 

... cosa succede? Devo controllare se ref è null prima di ogni istruzione (questo è sbagliato, ma cosa devo fare )? Ci scusiamo per le domande a risposta rapida, ma ho difficoltà a comprendere queste classi Reference ... Grazie!

+0

Perché c'è una 'WeakHashMap' ma nessuna' SoftHashMap' o 'PhantomHashMap'? Domanda eccellente, perché non l'ho notato prima .. ?? –

risposta

6

Un link: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

PhantomHashMap non avrebbe funzionato molto bene come get restituisce sempre null i riferimenti fantasma.

Le cache sono difficili, quindi SoftHashMap potrebbe non funzionare come si potrebbe pensare. Tuttavia, credo che la raccolta di raccolte di Google contenga un'implementazione generale della mappa di riferimento.

Controllare sempre che get non restituisca null. (Nota, che non controlla che il riferimento allo Reference non sia- null.) Nel caso di stringhe internamente lo farà sempre, ma (come sempre) non cerca di essere "intelligente" a riguardo.

+0

Il link è scaduto. –

+0

@MehrajMalik Link corretto. –

57

La libreria Java documentation for the java.lang.ref package caratterizza la forza decrescente dei tre tipi di riferimento esplicito.

Si utilizza un SoftReference quando si desidera che l'oggetto di riferimento rimanga attivo finché il processo host non sta esaurendo la memoria. L'oggetto non sarà idoneo per la raccolta fino a quando il collettore necessita di per liberare memoria. In modo approssimativo, legare un SoftReference significa "Pin l'oggetto fino a quando non è più possibile".

Al contrario, utilizzare WeakReference quando non si desidera influenzare la durata dell'oggetto referenziato; vuoi semplicemente fare un'affermazione separata su l'oggetto di riferimento, a patto che rimanga in vita. L'idoneità dell'oggetto per la raccolta non è influenzata dalla presenza di bound WeakReference s. Qualcosa come un mapping esterno dall'istanza dell'oggetto alla proprietà correlata, in cui la proprietà deve essere registrata solo fino a quando l'oggetto correlato è vivo, è un buon uso per WeakReference se WeakHashMap.

L'ultimo - PhantomReference - è più difficile da caratterizzare. Come WeakReference, tale limite PhantomReference non esercita alcuna influenza sulla durata dell'oggetto referenziato. Ma a differenza degli altri tipi di riferimento, non è possibile nemmeno dereferenziare uno PhantomReference. In un certo senso, non punta alla cosa a cui punta, per quanto i chiamanti possano dire. Permette semplicemente di associare alcuni dati relativi all'oggetto referenziato - dati che possono essere successivamente controllati e messi in atto quando lo PhantomReference viene messo in coda nel suo correlato ReferenceQueue. Normalmente si ottiene un tipo da PhantomReference e sono inclusi alcuni dati aggiuntivi in ​​quel tipo derivato. Sfortunatamente, ci sono alcuni downcast coinvolti per fare uso di un tipo così derivato.

Nel codice di esempio, non è il riferimento ref (o, se si preferisce, "variabile") che può essere nullo. Piuttosto, è il valore ottenuto chiamando lo Reference#get() che potrebbe essere nullo. Se è risultato essere nullo, sei in ritardo; l'oggetto di riferimento è già in via di raccolta:

final String val = ref.get(); 
if (null != val) 
{ 
    // "val" is now pinned strongly. 
} 
else 
{ 
    // "val" is already ready to be collected. 
} 
0
String str = new String("hello, world"); 
    WeakReference<String> ref = new WeakReference<String>(str); 
    str = null; 
    if (ref != null) {     
     System.gc(); 
     System.out.println(ref.get()); 
    } 

In questo caso, verrà emesso nulla. E System.gc() è importante qui.