1. Confronti

I programmatori devono confrontare continuamente variabili diverse tra loro. Ma, come hai già visto, non tutto è così semplice.

I numeri interi sono molto facili da confrontare: basta usarli ==e il gioco è fatto. Per confrontare i numeri reali , devi confrontare la loro differenza (o meglio, il valore assoluto della differenza) con un numero molto piccolo.

Confrontare le stringhe è ancora più difficile. Soprattutto perché le stringhe sono oggetti. Inoltre, i programmatori spesso desiderano che il confronto tra stringhe avvenga in modo leggermente diverso a seconda della situazione.


2. Come sono disposte le stringhe in memoria

Come hai già visto, le stringhe vengono memorizzate in memoria in modo diverso rispetto agli interi e ai numeri reali:

Come sono disposte le stringhe memoria

Due blocchi di memoria vengono utilizzati per memorizzare le stringhe: un blocco memorizza il testo stesso (la sua dimensione dipende dalla dimensione del testo) mentre il secondo blocco (4 byte) memorizza l'indirizzo del primo blocco.

Sebbene un programmatore esperto direbbe qualcosa come "la String strvariabile memorizza un riferimento a un Stringoggetto.


3. Assegnazione di riferimenti a una stringa

I vantaggi di questo approccio diventano evidenti quando è necessario assegnare una variabile stringa a un'altra variabile stringa. Esempio:

String text = "This is a very important message";
String message = text;

Ed ecco cosa conterrà la memoria come risultato:

Assegnazione di riferimenti a una stringa

Dopo questo tipo di operazione di assegnazione, l' Stringoggetto rimane dov'era e solo il suo indirizzo (un riferimento all'oggetto) viene copiato nella messagevariabile.


4. Lavorare con riferimenti e oggetti

Ma se decidi di convertire una stringa in maiuscolo (lettere maiuscole), la macchina Java fa tutto bene: ti ritroverai con due Stringoggetti e le variabili texte messagememorizzeranno i riferimenti, ciascuno al proprio oggetto.

Esempio:

String text = "This is a very important message";
String message = text.toUpperCase(); 

Ed ecco cosa conterrà la memoria come risultato:

Lavorare con riferimenti e oggetti

Si noti che il toUpperCase()metodo non modifica la stringa su cui viene chiamato. Invece, crea una nuova stringa (nuovo oggetto) e restituisce un riferimento ad essa.

Che ne dici di un esempio ancora più interessante. Diciamo che decidi di passare una stringa a un Scanneroggetto (in modo che legga i valori dalla stringa).

Esempio:

String text = "10 20 40 80";
Scanner console = new Scanner(text);
int a = console.nextInt();
int b = console.nextInt();

Puoi saperne di più su come Scannerfunziona la classe qui .

Ecco come verrà tutto memorizzato:

Lavorare con riferimenti e oggetti.  Classe Scanner

In questo caso, un singolo Stringoggetto rimane in memoria così com'era: solo i riferimenti ad esso vengono passati e archiviati nelle variabili.


5. Confrontare i riferimenti agli Stringoggetti

E finalmente, siamo arrivati ​​alla parte divertente: il confronto tra stringhe.

Esistono due operatori che è possibile utilizzare per confrontare le variabili stringa: ==(uguale) e !=(diverso). Non è possibile utilizzare gli operatori "maggiore di", "minore di" o "maggiore o uguale a" — il compilatore non lo consentirà.

Ma c'è una sfumatura interessante qui: cosa viene effettivamente memorizzato nelle variabili stringa? Esatto: indirizzi (riferimenti) a oggetti. Ed è questi indirizzi che verranno confrontati:

String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase(); 

Ecco cosa rimarrà in memoria:

Confronto tra riferimenti e oggetti String

Le variabili messagee textsi riferiscono a (memorizzano l'indirizzo di) lo stesso oggetto. Ma le variabili s1e s2memorizzano riferimenti a oggetti molto simili ma distinti.

E se confronti queste 4 variabili nel codice, ottieni il seguente risultato:

Codice Uscita console
String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase();
System.out.println(text == message);
System.out.println(text == s1);
System.out.println(s1 == s2); 


true  // The addresses are equal
false // The addresses are different
false // The addresses are different