Come Confrontare Stringhe in Java
Confronta stringhe Java con equals, equalsIgnoreCase, compareTo ed evita l'errore classico con ==.
Confrontare due valori String in Java è una delle prime cose che un principiante sbaglia, perché l'operatore == confronta silenziosamente i riferimenti invece dei contenuti. Questo capitolo mostra i modi corretti e idiomatici per verificare l'uguaglianza e l'ordinamento delle stringhe — equals, equalsIgnoreCase, compareTo e il null-safe Objects.equals — e spiega esattamente quando ognuno è lo strumento giusto.
Per la ragione sottostante per cui letterali identici possono essere ==, consulta il string pool; per un'analisi più ampia delle tecniche di confronto, consulta il confronto di stringhe in Java.
Uguaglianza dei contenuti con equals
Per verificare se due stringhe contengono gli stessi caratteri, utilizza equals:
String a = "hello";
String b = new String("hello");
boolean same = a.equals(b); // true — same charactersequals scorre le due sequenze di caratteri e restituisce true solo quando hanno la stessa lunghezza e gli stessi caratteri nello stesso ordine. È il metodo che vuoi nel 99% delle volte in cui chiedi "queste due stringhe sono lo stesso testo?".
Un trucco difensivo comune è chiamare equals su un letterale stringa in modo che il ricevitore non sia mai null:
if ("yes".equals(userInput)) { ... } // safe even if userInput is nullPerché == è la trappola classica
== non guarda affatto i caratteri — chiede "sono esattamente lo stesso oggetto in memoria?". Poiché il compilatore interna i letterali stringa (memorizza una copia condivisa in un pool), due letterali identici possono risultare ==, il che induce le persone a pensare che == confronti il testo. Non è così: nel momento in cui una stringa proviene da new, dall'input dell'utente o dalla concatenazione a runtime, == restituisce false anche per testo identico.
| Espressione | Risultato | Motivo |
|---|---|---|
"java" == "java" | true | Entrambi fanno riferimento allo stesso letterale internato |
"java" == new String("java") | false | new crea un oggetto distinto |
"java".equals(new String("java")) | true | Confronta i contenuti, non l'identità |
Regola pratica: non usare mai == per confrontare stringhe. Usa equals.
Confronto senza distinzione tra maiuscole e minuscole con equalsIgnoreCase
Quando le maiuscole/minuscole non devono essere rilevanti — nomi utente, estensioni di file, nomi di intestazioni — usa equalsIgnoreCase:
"Java".equalsIgnoreCase("JAVA"); // trueApplica la stessa logica carattere per carattere di equals dopo aver uniformato il caso, quindi "README".equalsIgnoreCase("readme") è true.
Ordinamento con compareTo
Per ordinare o classificare le stringhe anziché semplicemente testare l'uguaglianza, usa compareTo, che restituisce il segno della differenza lessicografica (ordine dizionario):
"apple".compareTo("banana"); // negative — apple comes first
"apple".compareTo("apple"); // 0 — equal
"banana".compareTo("apple"); // positive — banana comes laterUn risultato negativo significa che il ricevitore viene prima dell'argomento, 0 significa uguale, positivo significa dopo. Esiste una variante compareToIgnoreCase e String.CASE_INSENSITIVE_ORDER da usare come Comparator. Nota che l'ordinamento predefinito è per punto di codice Unicode, quindi tutte le lettere maiuscole (A–Z) vengono prima di tutte le lettere minuscole.
Un esempio pratico
Questo programma mette in pratica ogni approccio fianco a fianco in modo da vedere esattamente come si comporta ciascuno.
Cosa osservare dall'esecuzione:
a == bstampafalseanche se entrambe le stringhe leggono "java", perchénew String("java")è un oggetto separato — prova che==confronta l'identità, non il testo.a.equals(b)stampatrue:equalsguarda i caratteri, che è quasi sempre ciò che si intende con "la stessa stringa".a == cstampatruesolo perché entrambi sono letterali che condividono un oggetto internato — questo successo accidentale è esattamente il motivo per cui==attira i principianti in un bug.equalsIgnoreCasestampatrueper"Java"vs"JAVA", mentrecompareTorestituisce0per testo identico e un segno non zero (-1per apple prima di banana) quando differiscono.Objects.equals(null, "x")stampafalseinvece di lanciare un'eccezione, e l'array ordinato stampa[Cherry, apple, banana]— laCmaiuscola (punto di codice 67) viene prima delle lettere minuscole (punto di codice 97+).
Quale metodo dovrei usare?
Scegli il confronto in base alla domanda a cui stai effettivamente rispondendo:
| Vuoi sapere… | Usa | Note |
|---|---|---|
| Il testo è esattamente uguale? | a.equals(b) | La scelta predefinita per l'uguaglianza |
| Uguale, ignorando maiuscole/minuscole? | a.equalsIgnoreCase(b) | Uniforma il caso prima |
Uguale, ma uno dei due potrebbe essere null? | Objects.equals(a, b) | Restituisce true per due null, non lancia mai eccezioni |
| Qual è il loro ordine di ordinamento? | a.compareTo(b) | Negativo / 0 / positivo |
| Ordine di ordinamento, ignorando il caso? | a.compareToIgnoreCase(b) | Oppure String.CASE_INSENSITIVE_ORDER come Comparator |
Un'abitudine utile: quando hai bisogno solo dell'uguaglianza, preferisci equals (o Objects.equals quando null è possibile) e mai compareTo(...) == 0, che fa strettamente più lavoro. Per esplorare i metodi su cui si basano, consulta i metodi delle stringhe Java e la classe String.