Se == confronta i riferimenti in Java, perché valuta su true con queste stringhe?

Come si afferma, l’operatore == confronta i riferimenti a oggetti per verificare se si riferiscono allo stesso object su un heap. In tal caso, perché sto ottenendo il “Uguale” per questo pezzo di codice?

public class Salmon { public static void main(String[] args) { String str1 = "Str1"; String str2 = "Str1"; if (str1 == str2) { System.out.println("Equal"); } else { System.out.println("Not equal"); } } } 

Il programma stamperà Equal . (Almeno usando il Sun Hotspot e il sole Javac.) Qui è dimostrato su http://ideone.com/8UrRrk

Ciò è dovuto al fatto che le costanti letterali stringa sono memorizzate in un pool di stringhe e i riferimenti alle stringhe possono essere riutilizzati.

Ulteriori letture:

  • Cos’è il pool letterale String?
  • String interning

Questo tuttavia:

 public class Salmon { public static void main(String[] args) { String str1 = "Str1"; String str2 = new String("Str1"); if (str1 == str2) { System.out.println("Equal"); } else { System.out.println("Not equal"); } } } 

Stamperà Not equal poiché è garantito che il new introduca un nuovo riferimento.

Quindi, regola generale: confronta sempre le stringhe usando il metodo equals .

Java memorizza tutte le stringhe internamente in una tabella di stringhe durante un’esecuzione. I riferimenti alle due stringhe sono identici perché nella memoria sono memorizzati nello stesso posto. Quindi, Equal .

La tua affermazione ha ragione, che == confronta i riferimenti a oggetti. Prova la stessa cosa con qualsiasi altra class ma con le stringhe e non otterrai lo stesso risultato.

Questo codice non stampa Equal .
Ma se le due stringhe fossero uguali, questo caso sarebbe speciale.

Ora che hai aggiornato il tuo codice, è il caso:

Una spiegazione semplice (ma non del tutto esatta) è che il compilatore vede che le due stringhe sono uguali e fanno qualcosa del tipo:

 String str1 = "Str1"; String str2 = str1; 

Quello che succede veramente qui è che il compilatore vedrà la stringa letterale e la inserirà nel “pool letterale String”.

Dato che una stringa non può essere modificata (è immutabile) i valori letterali di Stringhe (quelli trovati durante la compilazione) vengono inseriti in un “pool”.
In questo modo, se due stringhe letterali differenti che hanno lo stesso contenuto (come in questo caso particolare), la memoria non viene sprecata per memorizzare “Str1” e “Str1” due volte.

Gente, state dimenticando che il processo di collocare stringhe letterali nel pool si chiama “interning”. La class String ha un metodo chiamato intern (). Questo metodo inserisce qualsiasi stringa nel pool, anche se inizialmente non è nel pool (non letterale). Ciò significa che il codice come questo:

 String a = "hello"; String b = new String("hello"); b = b.intern(); System.out.println(a == b); 

stamperà ” true “. Ora, perché qualcuno dovrebbe aver bisogno di questo? Come puoi immaginare, il confronto delle stringhe a.equals(b) potrebbe richiedere molto tempo se le stringhe sono della stessa lunghezza ma diverse vicine alla fine. (Basta guardare il codice sorgente .equals ().).

Tuttavia, confrontare direttamente i riferimenti è lo stesso che confrontare gli interi (puntatori in linguaggio C), che è quasi istantaneo.

Quindi, cosa ti dà questo? Velocità. Se devi confrontare le stesse stringhe molte, molte volte, le prestazioni del tuo programma trarranno enormi benefici se condividi queste stringhe . Se tuttavia si intende confrontare le stringhe una sola volta, non ci sarà alcun guadagno in termini di prestazioni poiché il processo di interning stesso utilizza equals ().

Spero che questo lo spieghi.

Grazie

I commenti sopra lo hanno riassunto abbastanza bene.

Non ho un ambiente Java a portata di mano, ma tentare di fare quanto segue dovrebbe chiarire le cose per voi (speriamo che funzioni come previsto).

 String str1 = "Str1"; String str2 = "Str"; str2 += "1"; 

Dovrebbe ora stampare Non uguale