2016-06-22 12 views
15

Questo è il metodo keySet() sulla classe HashMap di JDK. Perché l'autore ha assegnato il campo (keySet) alla variabile locale ks?Assegna il campo dell'istanza alla variabile locale

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

Qual è la differenza tra sopra e sotto? Questo ha qualcosa a che fare con la sicurezza del thread?

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 
+0

Forse; anche se sembra che stia cercando di impostare una variabile di livello di classe, assicurando che la variabile non sia nullo e restituisca quel valore. Però non ne ho idea. Avrei bisogno di guardare l'intera classe. –

+0

Forse per chiarezza di intenzione – alphablue

+1

Potrebbe essere considerato come un duplicato di http://stackoverflow.com/q/28975415/3182664 http://stackoverflow.com/q/2785964/3182664 http://stackoverflow.com/q/ 37776179/3182664 http://stackoverflow.com/q/32619269/3182664 e probabilmente alcuni altri .... – Marco13

risposta

6

Per espandere leggermente La risposta di Michael, mi aspetto che sia lì per garantire che il metodo keySet() non restituisca mai null, possibilmente oltre a fornire vantaggi in termini di prestazioni.

Dato questo codice:

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 

Sarebbe almeno teoricamente possibile in codice multi-threaded che il campo keySet potrebbe essere impostato null tra la prima lettura (keySet == null) e la seconda lettura, dove viene restituito. Non ho guardato il resto del codice, ma presumo che ci siano altri posti in cui keySet è potenzialmente assegnato a null. Se questo è il risultato di un problema visto in natura, o una misura difensiva sarebbe una domanda per gli autori.

Il codice attuale:

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

... non ha questo problema come il campo viene letto solo una volta.

+0

Sì. Si tratta di essere al sicuro in un ambiente multi-thread. –

+0

@msandiford non è necessariamente impostato su null da qualche parte, le operazioni potrebbero essere semplicemente riordinate in quanto vi sono due letture vivaci della variabile condivisa. – Eugene

8

Se si guarda la dichiarazione keySet nel abstract class AbstractMap<K,V>, vedrete che è definito come:

transient volatile Set<K> keySet; 

Dal momento che è volatile, leggerlo solo una volta utilizzando l'assegnazione variabile locale è più economico che leggerlo due volte come sarebbe nell'altro esempio che hai fornito.

Inoltre, se si dovesse tornare direttamente alla variabile keySet, quindi tutto il codice cliente sarebbe avere a che fare con un riferimento volatili rispetto a un riferimento non volatile (cioè la Set<K> ks)

+2

Grazie per la risposta sul campo volatile letto, non ci ho pensato. Potresti spiegare per favore "trattare un riferimento volatile rispetto a un riferimento non volatile"? – joohwan

+1

Non esiste una nozione come "riferimento volatile rispetto a un riferimento non volatile". – Boann

+0

@Boann Che è corretto. Grazie. –

Problemi correlati