2012-03-14 10 views
52

Ho le seguenti righe di codici per confrontare String. str1 non è uguale a str2, che è comprensibile dal momento che confronta il riferimento all'oggetto. Ma allora perché s1 è uguale a s2?Ciò che rende il confronto dei riferimenti (==) funziona con alcune stringhe in Java?

String s1 = "abc"; 
String s2 = "abc"; 

String str1 = new String("abc"); 
String str2 = new String("abc"); 

if (s1==s2) 
    System.out.println("s1==s2");   
else 
    System.out.println("s1!=s2"); 

if (str1==str2) 
    System.out.println("str1==str2");   
else 
    System.out.println("str1!=str2"); 

if (s1==str1) 
    System.out.println("str1==s1");   
else 
    System.out.println("str1!=s1"); 

uscita:

s1==s2 
    str1!=str2 
    str1!=s1 
+12

Hai provato a cercare SO prima? :( –

+13

http://stackoverflow.com/questions/7144059/java-string-pool-object-creation, http://stackoverflow.com/questions/4033625/if-compares-references-in-java-why-does -it-evaluate-to-true-with-these-strin, http://stackoverflow.com/questions/6377058/string-reference, http://stackoverflow.com/questions/1903094/java-strings-and-stringpool –

+1

(Non sto chiudendo questo, perché non ho trovato un'altra domanda * come focalizzata * come questa, ma sono sicuro che esiste anche –

risposta

80

La stringa pool di costanti sarà essenzialmente nella cache tutti i letterali stringa in modo che siano lo stesso oggetto sottostante, ed è per questo che si vede l'uscita si fa per s1==s2. È essenzialmente un'ottimizzazione nella VM per evitare di creare un nuovo oggetto stringa ogni volta che viene dichiarato un valore letterale, che potrebbe diventare molto costoso molto rapidamente! Con l'esempio str1==str2, stai dicendo esplicitamente alla VM di creare nuovi oggetti stringa, quindi perché è falso.

Come parte, chiamando il metodo intern() su qualsiasi stringa lo si aggiungerà al pool costante (e restituirà la stringa che è stata aggiunta al pool.) Non è necessariamente una buona idea farlo comunque se non si è sicuri hai a che fare con stringhe che saranno sicuramente utilizzate come costanti, altrimenti potresti finire per creare difficoltà a rintracciare le perdite di memoria.

+2

Mi hai battuto solo 2 secondi dando l'idea del metodo intern() –

+6

Posticipa perdi. haha ​​j/k. = P –

+1

+1 ma vale anche la pena notare che l'aggiunta di molte stringhe al pool costante in generale è una cattiva idea poiché può causare perdite di memoria difficili da rilevare. Fallo solo per un numero limitato di stringhe che verranno effettivamente utilizzate come costanti (ad esempio le chiavi HashMap), mai per dati String arbitrari. – mikera

18

s1 e s2 sono stringhe letterali. Quando si crea un nuovo valore letterale String il compilatore verifica innanzitutto se qualsiasi letterale che rappresenta lo stesso sia presente o meno nel pool di stringhe. Se ce n'è uno, il compilatore restituisce quello letterale, altrimenti il ​​compilatore ne crea uno nuovo.

Quando è stata creata la stringa s2, il compilatore restituisce la stringa s1 dal lotto come già creata in precedenza. Questo è il motivo per cui lo s1 e lo s2 sono gli stessi. Questo comportamento si chiama interning.

+0

Sono un po 'confuso quando dici che "il compilatore ne crea uno nuovo". AFAIK, il compilatore è pensato per creare il codice macchina intermedio e in realtà non esegue (quindi crea) alcun oggetto in memoria. Intendevi che il compilatore _replaces_ string letterals? Si prega di chiarire questo. – peakit

+0

Al momento non ho documentazione di supporto, ma credo che @Chandra Sekhar si riferisse al compilatore JIT o Just In Time e non al compilatore javac. – Robert

3

In Java, le stesse stringhe costanti verranno riutilizzate. In modo che s1 e s2 puntino allo stesso oggetto "abc" e s1==s2. Ma quando si utilizza new String("abc"), verrà creato un altro oggetto. In modo che s1 != str1.

5

Ciò è dovuto al fatto che i valori letterali delle stringhe sono internati. A questo proposito, Java documentations dice:

Tutte le stringhe letterali e stringhe a valore espressioni costanti sono internati

e questo spiega perché s1 e s2 sono gli stessi (queste due variabili puntare allo stesso internato stringa)

9

Questo fenomeno è dovuto a String interning.

Fondamentalmente, tutti i valori letterali di stringa sono "memorizzati nella cache" e riutilizzati.

0

Come string è immutabile in Java, tutte le string literals memorizzato nella cache per la riusabilità.

Quando si crea oggetto String usando l'operatore new(), crea sempre un nuovo oggetto nella memoria heap. D'altra parte, se si crea un oggetto usando la sintassi letterale String, ad es."Java", può restituire un oggetto esistente dal pool di stringhe (una cache di oggetto String nello spazio di gen Perm, che viene ora spostato nello spazio heap nella recente versione di Java), se già esiste. Altrimenti creerà un nuovo oggetto stringa e inserirà un pool di stringhe per il riutilizzo futuro.

String s1 = new String("java"); 
String s2 = new String("java"); 
String s3 = "java"; 
String s4 = "java"; 

enter image description here

Please refer this link