2015-04-26 5 views
14

Sono davvero confuso da come string interning funziona in Java. Quando scrivo:Lo internamento delle stringhe viene eseguito in fase di compilazione in Java?

String a = "ABC"; 
String b = "ABC"; 

if (a==b) 
    System.out.println("Equal"); 

Il compilatore memorizza la stringa letterale "ABC" nel lotto costante di stringhe in fase di compilazione?

Che suona illogico, perché ho pensato che la stringa di piscina costante è stato creato dalla JVM in fase di esecuzione, e non vedo come ciò sia possibile, se lo si fa al momento della compilazione in quanto il compilatore Java non ha nemmeno invocare la JVM .

Se non viene eseguito in fase di compilazione e viene eseguito in fase di esecuzione, perché il seguente comando restituisce false (preso da this answer)?

// But .substring() is invoked at runtime, generating distinct objects 
"test" == "!test".substring(1) // --> false 

Se eseguito in fase di esecuzione, perché la JVM non riesce a capire che si tratta della stessa stringa?

Sono davvero confuso su come lo string interning funziona in Java e dove viene memorizzato esattamente il pool di stringhe Java.

+0

Il seguente link è perspicace: http://stackoverflow.com/questions/513832/ how-do-i-compare-stringhe-in-java – Zyn

+0

Non sono sicuro della prima parte della tua domanda, ma 'substring' restituisce un * nuovo * oggetto, e così mentre il contenuto di entrambe le stringhe corrisponde a' test ', poiché non sono lo stesso oggetto' == 'restituisce false. –

+2

È il compilatore. Non capisco perché dici che non può sia mettere le stringhe nel pool costante di stringhe.Il compilatore inserirà le stringhe costanti all'interno di una posizione di memoria, quindi all'avvio del programma la JVM caricherà quella memoria e creerà il pool costante da utilizzare in fase di runtime, ma il pool verrà configurato dal compilatore. – Bakuriu

risposta

18

Il compilatore inserisce le stringhe letterali nel file di classe (e solo quelle univoche, consolida tutti i letterali equivalenti); la JVM carica tali stringhe nel pool di stringhe quando viene caricato il file di classe.

Se eseguito in fase di esecuzione, perché la JVM non può capire che si tratta della stessa stringa.

Poiché la stringa viene restituito da .substring non è stato internati, e così è un oggetto diverso dal "test" stringa equivalente nel pool stringa. Se internato, si otterrebbe true:

"test" == "!test".substring(1).intern() // true 

Sezioni §4.4 of the JLS e §5.3 of the JVM spec guardano rilevante.


Giusto per essere chiari: Il modo corretto per confrontare le stringhe in Java è quello di utilizzare il metodo .equals o simile, non ==. L'utilizzo di == con istanze di stringa è in genere errato. (A meno che non si sta giocando con la comprensione quando e come le cose sono internati ...)

+1

La documentazione per la sottostringa @ http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int) specifica in modo specifico che restituisce un * nuovo * oggetto stringa. –

+0

Basta aggiungere qualche dettaglio. Bella risposta. –

+0

@ T.J.Crowder quindi 'intern()' evita il nuovo oggetto giusto? –

0

ho controllato .class per

String a = "ABC"; 
String b = "ABC"; 

e trovato solo una "ABC" in esso. Questo è javac crea una costante della stessa stringa in fase di compilazione.

Ma se 2 o più classi hanno lo stesso "ABC" costante allora JVM li metterà nella stessa posizione nel pool di stringa