I've been using the =
operator in my program to compare all my strings so far.
Jednak natknąłem się na błąd, zmieniłem jeden z nich na .equals()
zamiast, i to naprawiło błąd.
Czy =
jest złe? Kiedy powinien, a kiedy nie powinien być używany? Jaka jest różnica?
==
testuje równość referencji (czy są tym samym obiektem).
.equals()
testuje równość wartości (czy są one logicznie "równe").
Objects.equals() sprawdza czy nie ma null
przed wywołaniem .equals()
, więc nie musisz tego robić (dostępne od JDK7, dostępne również w Guava).
String.contentEquals() porównuje zawartość String
z zawartością dowolnego CharSequence
(dostępne od Java 1.5).
W konsekwencji, jeśli chcesz przetestować czy dwa ciągi mają tę samą wartość, prawdopodobnie będziesz chciał użyć 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
Prawie zawsze chcesz użyć Objects.equals()
. W rzadkich sytuacjach, gdy wiesz, że masz do czynienia z interned łańcuchami, możesz użyć =
.
Z JLS 3.10.5. String Literals:
Co więcej, literał łańcuchowy zawsze odnosi się do tej samej instancji klasy
String
. Dzieje się tak, ponieważ literały łańcuchowe - lub, bardziej ogólnie, łańcuchy będące wartościami stałych wyrażeń (§15.28) - są "internowane" tak, aby dzielić unikalne instancje, używając metodyString.intern
.
Podobne przykłady można znaleźć również w JLS 3.10.5-1.
Tak, ==
jest złe dla porównywania Stringów (jakichkolwiek obiektów naprawdę, chyba że wiesz, że'są kanoniczne). =
po prostu porównuje referencje do obiektów. .equals()
testuje równość. Dla Stringów, często będą one'takie same, ale jak już odkryłeś, nie zawsze jest to gwarantowane.
`` porównuje referencje obiektów w Javie, i to nie jest wyjątek dla obiektów String
.
Do porównywania rzeczywistej zawartości obiektów (w tym String
), należy użyć metody equals
.
Jeśli porównanie dwóch obiektów String
przy użyciu =
okaże się true
, to dlatego, że obiekty String
zostały zintergowane, a maszyna wirtualna Javy ma wiele referencji wskazujących na tą samą instancję String
. Nie należy oczekiwać, że porównanie jednego obiektu String
zawierającego tę samą zawartość co inny obiekt String
przy użyciu =
będzie oceniane jako true
.