Do tej pory używałem ==
operatora w moim programie do porównywania wszystkich moich ciągów. Jednak natknąłem się na błąd, .equals()
zamiast tego zmieniłem jeden z nich i naprawiłem błąd.
Jest ==
źle? Kiedy powinien i nie powinien być używany? Co za różnica?
==
działa tak, jak działa na Obiektach: stackoverflow.com/a/19966154/2284641==
będzie działać przez pewien czas, ponieważ java ma pulę ciągów, w której próbuje ponownie wykorzystać odwołania do pamięci często używanych ciągów. Ale==
porównuje, że obiekty są równe, a nie wartości ... więc.equals()
jest to właściwe zastosowanie, którego chcesz użyć."12"=="1"+2
jest fałszywe (prawdopodobnie)Odpowiedzi:
==
testy równości odniesienia (czy są to ten sam obiekt)..equals()
sprawdza równość wartości (czy są one logicznie „równe”).Objects.equals () sprawdza
null
przed wywołaniem,.equals()
więc nie musisz (dostępne od JDK7, dostępne również w Guava ).W związku z tym, jeśli chcesz przetestować, czy dwa ciągi mają tę samą wartość, prawdopodobnie będziesz chciał użyć
Objects.equals()
.Prawie zawsze chcesz używać
Objects.equals()
. W rzadkich sytuacji, gdy znamy masz do czynienia z internowanych strun, to można użyć==
.Z JLS 3.10.5. Literały smyczkowe :
Podobne przykłady można również znaleźć w JLS 3.10.5-1 .
Inne metody do rozważenia
String.equalsIgnoreCase () równość wartości, która ignoruje wielkość liter.
String.contentEquals () porównuje zawartość
String
z zawartością dowolnegoCharSequence
(dostępnego od Java 1.5). Chroni Cię przed koniecznością zamiany StringBuffer itp. W String przed wykonaniem porównania równości, ale pozostawia ci sprawdzanie wartości null.źródło
==
sprawdza wartość zmiennej. Gdy masz obiekt, zmienna, która odwołuje się do obiektu, ma odwołanie do obiektu jako wartość . W ten sposób porównujesz odniesienia , porównując dwie zmienne==
. Porównując prymitywny typ danych, taki jakint
, to wciąż ten sam przypadek. Zmienna typuint
ma liczbę całkowitą jako wartość. W ten sposób porównujesz wartości dwóchint
s za pomocą==
. Jeśliint
jest to wartość zmiennej lub magicznej liczby, nie ma znaczenia. Ponadto: odniesienia jest tylko numer, który odnosi się do pamięci.==
testuje odwołania do obiektów,.equals()
testuje wartości ciągu.Czasami wygląda na to, że
==
porównuje wartości, ponieważ Java robi pewne rzeczy za kulisami, aby upewnić się, że identyczne ciągi w wierszu są w rzeczywistości tym samym obiektem.Na przykład:
Ale uważaj na wartości zerowe!
==
null
dobrze obsługuje łańcuchy, ale wywołanie.equals()
z łańcucha pustego spowoduje wyjątek:Więc jeśli wiesz, że to
fooString1
może być zerowe, powiedz to czytelnikowi piszącPoniższe są krótsze, ale mniej oczywiste jest, że sprawdza wartość null:
źródło
==
robić zawsze porównania wartości! (?.
. PrzekształciłobynullString1?.equals(nullString2);
się to w całkowicie zerową instrukcję. Jednak to nie pomaga, jeśli maszvalidString?.equals(nullString);
- to wciąż rzuca wyjątek.==
porównuje odniesienia do obiektów..equals()
porównuje wartości ciągu.Czasami
==
daje złudzenie porównywania wartości String, jak w następujących przypadkach:Wynika to z faktu, że po utworzeniu dowolnego literału łańcuchowego JVM najpierw szuka tego literału w puli łańcuchów, a jeśli znajdzie dopasowanie, to samo odniesienie zostanie podane do nowego łańcucha. Z tego powodu otrzymujemy:
(a == b) ===> true
Jednak
==
kończy się niepowodzeniem w następującym przypadku:W tym przypadku dla
new String("test")
instrukcji zostanie utworzony nowy ciąg na stercie, i to odwołanie zostanie przekazaneb
, więcb
zostanie podane odwołanie na stercie, a nie w puli ciągów.Teraz
a
wskazuje na ciąg znaków w puli ciągów, podczas gdyb
wskazuje ciąg na stercie. Z tego powodu otrzymujemy:if (a == b) ===> false.
Chociaż
.equals()
zawsze porównuje wartość parametru String, więc w obu przypadkach daje wartość true:Dlatego używanie
.equals()
jest zawsze lepsze.źródło
.equals()
Metoda klasy obiektowej porównuje instancje (referencje / adres), w których.equals()
metody klasy String są zastępowane w celu porównywania treści (znaków)String
obiekty, aby zaoszczędzić pamięć, coString
jest znane z tego, że jest niezmienne (mam nadzieję, że mówię to poprawnie tutaj). Sprawdź także stackoverflow.com/questions/3052442/…Do
==
kontroli operatora, aby zobaczyć, jeśli dwa ciągi są dokładnie tego samego obiektu..equals()
Metoda sprawdzi, czy dwa ciągi mają tę samą wartość.źródło
Ciągi w Javie są niezmienne. Oznacza to, że ilekroć spróbujesz zmienić / zmodyfikować ciąg, otrzymasz nową instancję. Nie możesz zmienić oryginalnego ciągu. Dokonano tego, aby można było buforować te instancje ciągów. Typowy program zawiera wiele odwołań do łańcuchów, a buforowanie tych instancji może zmniejszyć zużycie pamięci i zwiększyć wydajność programu.
Kiedy używasz operatora == do porównywania łańcucha, nie porównujesz zawartości łańcucha, ale w rzeczywistości porównujesz adres pamięci. Jeśli oba są równe, zwróci prawdę, a fałsz w przeciwnym razie. Natomiast równość w ciągu znaków porównuje zawartość ciągu.
Pytanie brzmi, czy wszystkie łańcuchy są buforowane w systemie, dlaczego?
==
zwraca false, a równa zwraca true? To jest możliwe. Jeśli utworzysz nowy ciąg znaków, tak jak wString str = new String("Testing")
końcu utworzysz nowy ciąg w pamięci podręcznej, nawet jeśli pamięć podręczna zawiera już ciąg o tej samej zawartości. Krótko mówiąc"MyString" == new String("MyString")
, zawsze zwróci fałsz.Java mówi także o funkcji intern (), której można użyć w ciągu znaków, aby stał się częścią pamięci podręcznej, aby
"MyString" == new String("MyString").intern()
zwrócił wartość true.Uwaga: operator == jest znacznie szybszy niż równy tylko dlatego, że porównujesz dwa adresy pamięci, ale musisz mieć pewność, że kod nie tworzy nowych instancji String w kodzie. W przeciwnym razie napotkasz błędy.
źródło
Upewnij się, że rozumiesz dlaczego. Jest tak, ponieważ
==
porównanie porównuje tylko odniesienia;equals()
metoda robi porównanie znak po znaku zawartości.Kiedy wywołujesz new for
a
ib
, każdy otrzymuje nowe odniesienie, które wskazuje na"foo"
w tabeli ciągów. Odniesienia są różne, ale treść jest taka sama.źródło
Tak, to źle ...
==
oznacza, że dwa odwołania do łańcucha są dokładnie tym samym obiektem. Być może słyszałeś, że tak jest, ponieważ Java zachowuje rodzaj dosłownej tabeli (co robi), ale nie zawsze tak jest. Niektóre ciągi są ładowane na różne sposoby, zbudowane z innych ciągów itp., Więc nigdy nie należy zakładać, że dwa identyczne ciągi są przechowywane w tym samym miejscu.Równa się robi dla ciebie prawdziwe porównanie.
źródło
Tak,
==
źle nadaje się do porównywania ciągów (tak naprawdę obiektów, chyba że wiesz, że są kanoniczne).==
po prostu porównuje odwołania do obiektów..equals()
testy na równość. W przypadku ciągów często będą one takie same, ale jak odkryłeś, nie zawsze jest to gwarantowane.źródło
Java ma pulę String, w której Java zarządza alokacją pamięci dla obiektów String. Zobacz Pule ciągów w Javie
Podczas sprawdzania (porównywania) dwóch obiektów za pomocą
==
operatora porównuje się równość adresów do puli ciągów. Jeśli dwa obiekty String mają te same odnośniki adresowych następnie powracatrue
, inaczejfalse
. Ale jeśli chcesz porównać zawartość dwóch obiektów String, musisz zastąpićequals
metodę.equals
jest w rzeczywistości metodą klasy Object, ale jest ona nadpisywana do klasy String i podana jest nowa definicja, która porównuje zawartość obiektu.Ale uwaga szanuje przypadek String. Jeśli chcesz porównywać bez rozróżniania wielkości liter, musisz wybrać metodę equalsIgnoreCase klasy String.
Zobaczmy:
źródło
equalsIgnoreCase
co może być pouczające dla świeższego.Zgadzam się z odpowiedzią zacherates.
Ale to, co możesz zrobić, to przywołać
intern()
swoje nieliteralne ciągi.Z przykładu zacherates:
Jeśli internujesz nie literalną równość ciągów to
true
:źródło
==
do porównywania ciągów.==
porównuje odwołania do obiektów w Javie i nie jest to wyjątkiem dlaString
obiektów.Aby porównać rzeczywistą zawartość obiektów (w tym
String
), należy użyćequals
metody .Jeśli okaże się , że porównano dwa używane
String
obiekty , to dlatego, że obiekty zostały internowane, a wirtualna maszyna Java ma wiele odwołań do tego samego wystąpienia . Nie należy się spodziewać, że porównanie jednego obiektu zawierającego tę samą zawartość, co inny obiekt wykorzystujący do oceny jako .==
true
String
String
String
String
==
true
źródło
.equals()
porównuje dane w klasie (przy założeniu, że funkcja jest zaimplementowana).==
porównuje położenia wskaźnika (położenie obiektu w pamięci).==
zwraca true, jeśli oba obiekty (NIE MÓWIĄC O PRIMITIVES) wskazują na SAMĄ instancję obiektu..equals()
zwraca true, jeśli dwa obiekty zawierają te same dane wequals()
porównaniu==
z JavąTo może ci pomóc.
źródło
==
wykonuje sprawdzenie równości odniesienia , czy 2 obiekty (w tym przypadku łańcuchy) odnoszą się do tego samego obiektu w pamięci.equals()
Metoda sprawdzi, czy zawartość lub te stany z 2 obiektów są takie same.Oczywiście
==
jest szybszy, ale da (może) dać fałszywe wyniki w wielu przypadkach, jeśli chcesz tylko powiedzieć, czy 2String
s zawierają ten sam tekst.Zdecydowanie zaleca się użycie
equals()
metody.Nie martw się o wydajność. Niektóre rzeczy zachęcające do korzystania
String.equals()
:String.equals()
pierwszych kontroli równości odniesienia (za pomocą==
), a jeśli 2 ciągi znaków są takie same przez odniesienie, dalsze obliczenia nie są przeprowadzane!String.equals()
następnie sprawdzi długości ciągów. Jest to również szybka operacja, ponieważString
klasa przechowuje długość łańcucha, nie trzeba liczyć znaków ani punktów kodowych. Jeśli długości różnią się, nie jest przeprowadzana dalsza kontrola, wiemy, że nie mogą być równe.Kiedy wszystko jest już powiedziane i zrobione, nawet jeśli mamy gwarancję, że ciągi są stażystami, użycie tej
equals()
metody nie jest tak ogólne, jak mogłoby się wydawać, zdecydowanie zalecany sposób. Jeśli chcesz wydajnego sprawdzania referencji, używaj wyliczeń, jeśli jest to zagwarantowane przez specyfikację języka i implementację, że ta sama wartość wyliczenia będzie tym samym obiektem (przez odniesienie).źródło
Obviously == is faster
- w rzeczywistości wdrożenie.equals(String)
pierwszych kontroli==
przed czymkolwiek innym, więc powiedziałbym, że prędkość jest prawie identyczna.public boolean equals(Object anObject) { if (this == anObject) { return true; } ...
Jeśli jesteś podobny do mnie, kiedy po raz pierwszy zacząłem używać Javy, chciałem użyć operatora „==”, aby sprawdzić, czy dwa wystąpienia String są równe, ale na lepsze lub gorsze, nie jest to właściwy sposób na zrobienie tego w Javie.
W tym samouczku pokażę kilka różnych sposobów prawidłowego porównywania ciągów Java, zaczynając od podejścia, którego używam przez większość czasu. Na końcu tego samouczka porównywania ciągów Java również omówię, dlaczego operator „==” nie działa podczas porównywania ciągów Java.
Opcja 1: Porównanie ciągów Java z metodą równości Przez większość czasu (może w 95% przypadków) porównuję ciągi z metodą równości klasy Java String, jak poniżej:
Ta metoda Ciąg znaków równości sprawdza dwa ciągi Java i jeśli zawierają dokładnie ten sam ciąg znaków, są uważane za równe.
Patrząc na szybki przykład porównania ciągów z metodą równości, gdyby przeprowadzono następujący test, dwa ciągi nie byłyby uważane za równe, ponieważ znaki nie są dokładnie takie same (przypadek znaków jest inny):
Ale gdy dwa ciągi zawierają dokładnie ten sam ciąg znaków, metoda równości zwróci true, jak w tym przykładzie:
Opcja 2: Porównanie ciągów z metodą equalsIgnoreCase
W niektórych testach porównania ciągów zignorujesz, czy ciągi znaków są wielkie czy małe. Jeśli chcesz przetestować ciągi pod kątem równości w sposób bez rozróżniania wielkości liter, użyj metody equalsIgnoreCase klasy String, w następujący sposób:
Opcja 3: Porównanie Java String z metodą CompareTo
Istnieje również trzeci, mniej powszechny sposób porównywania ciągów Java, i to z wykorzystaniem metody StringTerm porównania. Jeśli dwa ciągi są dokładnie takie same, metoda CompareTo zwróci wartość 0 (zero). Oto szybki przykład tego, jak wygląda ta metoda porównywania ciągów:
Pisząc o tej koncepcji równości w Javie, należy zauważyć, że język Java zawiera metodę równości w podstawowej klasie Java Object. Ilekroć tworzysz własne obiekty i chcesz zapewnić sposób sprawdzenia, czy dwa wystąpienia Twojego obiektu są „równe”, powinieneś zastąpić (i zaimplementować) tę metodę równości w swojej klasie (w taki sam sposób, jak zapewnia język Java) to zachowanie równości / porównania w metodzie String equals).
Możesz rzucić okiem na to ==, .equals (), CompareTo () i Compare ()
źródło
Funkcjonować:
Test:
źródło
==
iequals
zostało już odebrane przez inne rozwiązania, po prostu zaproponował inny sposób porównywania ciągów w luźny sposób==
Check operator jeśli oba odwołania kierowane do tego samego obiektu, czy też nie..equals()
sprawdź rzeczywistą zawartość ciągu (wartość).Zauważ, że
.equals()
metoda należy do klasyObject
(superklasa wszystkich klas). Musisz go zastąpić zgodnie z wymaganiami klasy, ale dla String jest już zaimplementowany i sprawdza, czy dwa łańcuchy mają tę samą wartość, czy nie.Przypadek 1
Powód: Literały ciągów utworzone bez wartości zerowej są przechowywane w puli ciągów w obszarze permgen sterty. Zatem zarówno s1, jak i s2 wskazują na ten sam obiekt w puli.
Przypadek 2
Powód: Jeśli utworzysz obiekt String za pomocą
new
słowa kluczowego, na stercie zostanie mu przydzielone oddzielne miejsce.źródło
==
porównuje wartość referencyjną obiektów, podczas gdyequals()
metoda obecna wjava.lang.String
klasie porównuje zawartośćString
obiektu (do innego obiektu).źródło
equals()
metodaString
jest właściwie wString
klasie, a nie wObject
. Wartość domyślnaequals()
wObject
nie porównałaby, że zawartość jest taka sama, i w rzeczywistości zwraca wartość true, gdy odwołanie jest takie samo.Myślę, że definiując obiekt
String
, definiujesz obiekt. Więc musisz użyć.equals()
. Kiedy używasz pierwotnych typów danych, których używasz,==
ale zString
(i dowolnym obiektem) musisz użyć.equals()
.źródło
Jeśli
equals()
metoda jest obecna wjava.lang.Object
klasie i oczekuje się, że sprawdzi równoważność stanu obiektów! Oznacza to zawartość przedmiotów. Natomiast==
operator powinien sprawdzić, czy rzeczywiste instancje obiektów są takie same, czy nie.Przykład
Rozważ dwie różne zmienne odniesienia
str1
istr2
:Jeśli korzystasz z
equals()
Otrzymasz wynik tak
TRUE
, jakbyś go używał==
.Teraz dostaniesz
FALSE
jako wyjście, ponieważ obastr1
istr2
są skierowane do dwóch różnych obiektów, chociaż obaj dzielić tę samą treść napisów. Jest tak, ponieważnew String()
za każdym razem tworzony jest nowy obiekt.źródło
Operator == jest zawsze przeznaczony do porównywania referencji obiektowych , podczas gdy metoda String .equals () jest nadpisywana do porównywania treści :
źródło
Wszystkie obiekty mają zagwarantowaną
.equals()
metodę, ponieważ Object zawiera metodę.equals()
, która zwraca wartość logiczną. Zadaniem podklasy jest zastąpienie tej metody, jeśli wymagana jest dalsza definicja. Bez tego (tj. Przy użyciu==
) tylko adresy pamięci są sprawdzane między dwoma obiektami pod kątem równości. Ciąg zastępuje tę.equals()
metodę i zamiast używać adresu pamięci zwraca porównanie ciągów znaków na poziomie równości.Kluczową uwagą jest to, że łańcuchy są przechowywane w jednej puli brył, więc po utworzeniu łańcucha są one zawsze przechowywane w programie pod tym samym adresem. Ciągi się nie zmieniają, są niezmienne. Dlatego złym pomysłem jest stosowanie regularnej konkatenacji ciągów, jeśli masz poważne problemy z przetwarzaniem ciągów. Zamiast tego skorzystasz z
StringBuilder
dostarczonych klas. Pamiętaj, że wskaźniki tego ciągu mogą się zmienić, a jeśli chciałbyś sprawdzić, czy dwa wskaźniki były takie same,==
byłby to dobry sposób. Same łańcuchy nie.źródło
final String
zmienne) i ciągi, które Twój program jawnie internuje, są przechowywane w tak zwanej puli brył. Wszystkie inneString
obiekty podlegają usuwaniu elementów bezużytecznych, gdy nie ma już żadnych żywych odniesień do nich, tak jak każdy inny typ obiektu. Ponadto, chociaż niezmienność jest wymagana do działania całego mechanizmu internowania, nie ma w tym przypadku znaczenia.Możesz także użyć tej
compareTo()
metody do porównania dwóch ciągów. Jeśli wynikiem porównania jest 0, wówczas dwa ciągi są równe, w przeciwnym razie porównywane ciągi nie są równe.==
Porównuje referencje i nie porównać rzeczywiste ciągi. Jeśli utworzyłeś każdy ciąg za pomocąnew String(somestring).intern()
, możesz użyć==
operatora do porównania dwóch ciągów, w przeciwnym razie można użyć tylko metod equals () lub CompareTo.źródło
W Javie, gdy operator „==” jest używany do porównywania 2 obiektów, sprawdza, czy obiekty odnoszą się do tego samego miejsca w pamięci. Innymi słowy, sprawdza, czy 2 nazwy obiektów są w zasadzie odniesieniami do tej samej lokalizacji pamięci.
Klasa Java String faktycznie przesłania domyślną implementację equals () w klasie Object - i przesłania metodę, tak aby sprawdzała tylko wartości łańcuchów, a nie ich położenia w pamięci. Oznacza to, że jeśli wywołasz metodę equals () w celu porównania 2 obiektów String, to dopóki rzeczywista sekwencja znaków jest równa, oba obiekty są uważane za równe.
źródło