Hvordan sammenligner jeg strenger i Java?

Jeg har brukt ==-operatoren i programmet mitt for å sammenligne alle strengene mine så langt. Imidlertid løp jeg inn i en feil, endret en av dem til .equals() i stedet, og det løste feilen.

Er == dårlig? Når skal det og bør det ikke brukes? Hva er forskjellen?

Løsning

== tester for referanselikhet (om de er det samme objektet).

.equals() tester for verdilikhet (om de er logisk "like").

Objects.equals() sjekker for null før du kaller .equals() slik at du ikke trenger å gjøre det (tilgjengelig fra og med JDK7, også tilgjengelig i Guava).

String.contentEquals() sammenligner innholdet i String med innholdet i en hvilken som helst CharSequence (tilgjengelig siden Java 1.5).

Hvis du vil teste om to strenger har samme verdi, vil du derfor sannsynligvis bruke Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Du vil nesten alltid bruke Objects.equals(). I den sjeldne situasjonen der du vet at du har å gjøre med interned strenger, kan du bruke ==.

Fra JLS 3.10.5. String Literals:

Dessuten refererer en strengliteral alltid til samme instans av klassen String. Dette er fordi strenglitteraler - eller, mer generelt, strenger som er verdiene av konstantuttrykk (§15.28) - er "internert" for å dele unike forekomster, ved hjelp av metoden String.intern.

Lignende eksempler finnes også i JLS 3.10.5-1.

Kommentarer (0)

Ja, == er dårlig for å sammenligne strenger (egentlig alle objekter, med mindre du vet at de er kanoniske). == sammenligner bare objektreferanser. .equals() tester for likhet. For strenger vil de ofte være like, men som du har oppdaget, er det ikke alltid garantert.

Kommentarer (0)

== sammenligner objektreferanser i Java, og det er ikke noe unntak for String-objekter.

For å sammenligne det faktiske innholdet i objekter (inkludert String), må man bruke equals-metoden.

Hvis en sammenligning av to String-objekter ved hjelp av == viser seg å være true, er det fordi String-objektene ble internalisert, og Java Virtual Machine har flere referanser som peker til samme forekomst av String. Man bør ikke forvente at sammenligning av et String-objekt med samme innhold som et annet String-objekt ved hjelp av == skal evalueres som true.

Kommentarer (0)