Jak porównać ciągi w Javie?


724

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?


12
Warto również wiedzieć, że jeśli przesłonisz metodę .equals (), upewnij się, że przesłonisz metodę .hashcode (), w przeciwnym razie skończy się to naruszeniem relacji równoważności b / w równej i hashcode. Aby uzyskać więcej informacji, zapoznaj się z dokumentacją java.
Nageswaran

Pozostawiając link do mojego wyjaśnienia, dlaczego ==działa tak, jak działa na Obiektach: stackoverflow.com/a/19966154/2284641
Johannes H.

==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ć.
James Oravec

Nigdy nie używaj == do testowania, czy ciągi są takie same, chyba że lubisz śledzić subtelne błędy i badać zawiłości procesu internalizacji ciągów Java. "12"=="1"+2jest fałszywe (prawdopodobnie)
Flight Odyssey,

Odpowiedzi:


5559

== 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 nullprzed 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().

// 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ż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 :

Co więcej, literał łańcuchowy zawsze odnosi się do tego samego wystąpienia klasy String. Wynika to z tego, że literały łańcuchowe - lub, bardziej ogólnie, łańcuchy, które są wartościami wyrażeń stałych ( § 15.28 ) - są „internowane” w celu współużytkowania unikalnych instancji przy użyciu tej metody String.intern.

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ść Stringz zawartością dowolnego CharSequence(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.


3
Jeśli == sprawdza równość odniesienia, dlaczego n == 5 ma sens? 5 nie jest zmienną
Hrit Roy

2
@HritRoy Ponieważ ==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 jak int, to wciąż ten sam przypadek. Zmienna typu intma liczbę całkowitą jako wartość. W ten sposób porównujesz wartości dwóch ints za pomocą ==. Jeśli intjest to wartość zmiennej lub magicznej liczby, nie ma znaczenia. Ponadto: odniesienia jest tylko numer, który odnosi się do pamięci.
akuzminykh

718

==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:

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

Ale uważaj na wartości zerowe!

==nulldobrze obsługuje łańcuchy, ale wywołanie .equals()z łańcucha pustego spowoduje wyjątek:

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

Więc jeśli wiesz, że to fooString1może być zerowe, powiedz to czytelnikowi pisząc

System.out.print(fooString1 != null && fooString1.equals("bar"));

Poniższe są krótsze, ale mniej oczywiste jest, że sprawdza wartość null:

System.out.print("bar".equals(fooString1));  // "bar" is never null
System.out.print(Objects.equals(fooString1, "bar"));  // Java 7 required

86
Czasami wygląda to tak jakby „==” porównuje wartości - == robić zawsze porównania wartości! (
Tyle,

6
Niestety, nie ma metody statycznej dla isNullOrEmpty () i nie ma niestandardowego przeciążenia operatorów, co powoduje, że ta część Java jest bardziej skomplikowana niż w języku C # lub Python. A ponieważ Java nie ma metod rozszerzenia, nie możesz napisać własnego narzędzia do rozszerzenia pliku java.lang.String. Dobrze? Wszelkie przemyślenia na temat podklasy String, dodania tej statycznej metody narzędzia, a następnie zawsze używania MyString? Przydałaby się również metoda statyczna z dwoma parametrami do przeprowadzania porównań zerowo bezpiecznych w tej podklasie.
Jon Coombs

7
Groovy sprawia, że to trochę łatwiej z bezpiecznym operatorem nawigacji ( groovy.codehaus.org/... ) ?.. Przekształciłoby nullString1?.equals(nullString2);się to w całkowicie zerową instrukcję. Jednak to nie pomaga, jeśli masz validString?.equals(nullString);- to wciąż rzuca wyjątek.
Charles Wood,

5
Krótkie metody porównywania łańcuchów dopuszczających wartości zerowe w java: stackoverflow.com/questions/11271554/…
Vadzim

5
@JonCoombs Java obsługuje podklasę i tworzenie własnej metody. Jakkolwiek kilka klas jest oznaczonych jako ostateczne z pewnych powodów, String jest jedną z nich, więc nie możemy rozszerzyć. Możemy stworzyć inną klasę i stworzyć tam klasę użyteczności, która przyjmuje dwa ciągi argumentów i implementuje tam naszą logikę. Również dla zerowania sprawdź inne biblioteki, takie jak spring i apache, dobre kolekcje metod, można tego użyć.
Panther

442

== 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:

String a="Test";
String b="Test";
if(a==b) ===> true

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

                       String Pool
     b -----------------> "test" <-----------------a

Jednak ==kończy się niepowodzeniem w następującym przypadku:

String a="test";
String b=new String("test");
if (a==b) ===> false

W tym przypadku dla new String("test")instrukcji zostanie utworzony nowy ciąg na stercie, i to odwołanie zostanie przekazane b, więc bzostanie podane odwołanie na stercie, a nie w puli ciągów.

Teraz awskazuje na ciąg znaków w puli ciągów, podczas gdy bwskazuje ciąg na stercie. Z tego powodu otrzymujemy:

if (a == b) ===> false.

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

Chociaż .equals()zawsze porównuje wartość parametru String, więc w obu przypadkach daje wartość true:

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

Dlatego używanie .equals()jest zawsze lepsze.


3
.equals () porównuje dwa wystąpienia, jednak w celu ich porównania zaimplementowano równość. To może, ale nie musi, porównywać wyjście toString.
Jakub

3
@Jacob .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)
Satyadev

1
Dobrze wskazując różnice między pulą ciągów a stertą Java, ponieważ z pewnością nie są takie same. W puli ciągów Java próbuje „buforować” Stringobiekty, aby zaoszczędzić pamięć, co Stringjest znane z tego, że jest niezmienne (mam nadzieję, że mówię to poprawnie tutaj). Sprawdź także stackoverflow.com/questions/3052442/…
Roland

1
Oto odpowiedź, której szukałem.
Weezy

Co za świetna odpowiedź!
alwbtc


179

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 w String 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.


147
String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

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 ai b, każdy otrzymuje nowe odniesienie, które wskazuje na "foo"w tabeli ciągów. Odniesienia są różne, ale treść jest taka sama.


128

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.


124

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.


118

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 powraca true, inaczej false. Ale jeśli chcesz porównać zawartość dwóch obiektów String, musisz zastąpić equalsmetodę.

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.

Example:
    stringObjectOne.equals(stringObjectTwo);

Ale uwaga szanuje przypadek String. Jeśli chcesz porównywać bez rozróżniania wielkości liter, musisz wybrać metodę equalsIgnoreCase klasy String.

Zobaczmy:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE

7
Widzę, że to późna odpowiedź na wielkie pytanie. Czy mogę zapytać, co zawiera, a czego nie ma w istniejących odpowiedziach?
Mysticial

6
@Mysticial dodał, equalsIgnoreCaseco może być pouczające dla świeższego.
AmitG

103

Zgadzam się z odpowiedzią zacherates.

Ale to, co możesz zrobić, to przywołać intern()swoje nieliteralne ciągi.

Z przykładu zacherates:

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

Jeśli internujesz nie literalną równość ciągów to true:

new String("test").intern() == "test" ==> true 

8
To na ogół nie jest dobry pomysł. Staż jest stosunkowo drogi i może (paradoksalnie) >> zwiększyć << zużycie pamięci JVM i zwiększyć koszty GC. W większości przypadków przeważają one nad korzyściami wynikającymi z zastosowania ==do porównywania ciągów.
Stephen C,

101

==porównuje odwołania do obiektów w Javie i nie jest to wyjątkiem dla Stringobiektów.

Aby porównać rzeczywistą zawartość obiektów (w tym String), należy użyć equalsmetody .

Jeśli okaże się , że porównano dwa używane Stringobiekty , 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 .==trueStringStringStringString==true


99

.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 w equals()porównaniu ==z Javą

To może ci pomóc.


95

==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 2 Strings 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():

  1. Wdrożenie 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!
  2. Jeśli odniesienia do 2 ciągów znaków nie są takie same, String.equals()następnie sprawdzi długości ciągów. Jest to również szybka operacja, ponieważ Stringklasa 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.
  3. Tylko jeśli dotrzemy tak daleko, zawartość 2 łańcuchów zostanie faktycznie porównana i będzie to porównanie skrótowe: nie wszystkie znaki zostaną porównane, jeśli znajdziemy niedopasowany znak (w tej samej pozycji w 2 łańcuchach ), dalsze znaki nie będą sprawdzane.

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).


2
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.
Razzle Shazl

2
public boolean equals(Object anObject) { if (this == anObject) { return true; } ...
Razzle Shazl

82

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:

if (string1.equals(string2))

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):

String string1 = "foo";
String string2 = "FOO";

if (string1.equals(string2))
{
    // this line will not print because the
    // java string equals method returns false:
    System.out.println("The two strings are the same.")
}

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:

String string1 = "foo";
String string2 = "foo";

// test for equality with the java string equals method
if (string1.equals(string2))
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

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:

String string1 = "foo";
String string2 = "FOO";

 // java string compare while ignoring case
 if (string1.equalsIgnoreCase(string2))
 {
     // this line WILL print
     System.out.println("Ignoring case, the two strings are the same.")
 }

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:

String string1 = "foo bar";
String string2 = "foo bar";

// java string compare example
if (string1.compareTo(string2) == 0)
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

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 ()


5
dla literałów łańcuchowych Like String string1 = "foo bar"; String string2 = "foo bar"; możesz bezpośrednio użyć operatora == do przetestowania równości treści
JAVA,

1
W skrypcie aplikacji Google skrypt „CompareTo” nie jest możliwy. Próbowałem instaed „równa się” To było jedyne rozwiązanie, które działa ....
user3887038

77

Funkcjonować:

public float simpleSimilarity(String u, String v) {
    String[] a = u.split(" ");
    String[] b = v.split(" ");

    long correct = 0;
    int minLen = Math.min(a.length, b.length);

    for (int i = 0; i < minLen; i++) {
        String aa = a[i];
        String bb = b[i];
        int minWordLength = Math.min(aa.length(), bb.length());

        for (int j = 0; j < minWordLength; j++) {
            if (aa.charAt(j) == bb.charAt(j)) {
                correct++;
            }
        }
    }

    return (float) (((double) correct) / Math.max(u.length(), v.length()));
}

Test:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this
// Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);

6
Czym różni się to od innych odpowiedzi? i dlaczego to zrobić tak, jak sugerujesz
użytkownik151019

2
@Mark pytanie o różnicę między ==i equalszostało już odebrane przez inne rozwiązania, po prostu zaproponował inny sposób porównywania ciągów w luźny sposób
Khaled.K

77

==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 klasy Object(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

    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true

    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

    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true

    Powód: Jeśli utworzysz obiekt String za pomocą newsłowa kluczowego, na stercie zostanie mu przydzielone oddzielne miejsce.


53

==porównuje wartość referencyjną obiektów, podczas gdy equals()metoda obecna w java.lang.Stringklasie porównuje zawartość Stringobiektu (do innego obiektu).


15
nie być wybrednym, ale equals()metoda Stringjest właściwie w Stringklasie, a nie w Object. Wartość domyślna equals()w Objectnie porównałaby, że zawartość jest taka sama, i w rzeczywistości zwraca wartość true, gdy odwołanie jest takie samo.
Jacob Schoen,

1
@JacobSchoen: Powyższy link już nie działa, ponieważ GrepCode jest wyłączony. Oto alternatywa dla implementacji równości: [Inline Link] ( zgrepcode.com/java/openjdk/10.0.2/java.base/java/lang/… )
Amandeep Singh

50

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 z String(i dowolnym obiektem) musisz użyć .equals().


7
„char []” nie jest prymitywnym typem danych! Jest to tablica „char”. A tablice same w sobie nie są prymitywnymi typami danych.
Christian

48

Jeśli equals()metoda jest obecna w java.lang.Objectklasie 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 str1i str2:

str1 = new String("abc");
str2 = new String("abc");

Jeśli korzystasz z equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE");

Otrzymasz wynik tak TRUE, jakbyś go używał ==.

System.out.println((str1==str2) ? "TRUE" : "FALSE");

Teraz dostaniesz FALSEjako wyjście, ponieważ oba str1i str2są 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.


43

Operator == jest zawsze przeznaczony do porównywania referencji obiektowych , podczas gdy metoda String .equals () jest nadpisywana do porównywania treści :

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); // It prints false (reference comparison)
System.out.println(s1.equals(s2)); // It prints true (content comparison)

40

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 StringBuilderdostarczonych 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.


2
„po utworzeniu łańcucha jest on na zawsze zapisywany w programie pod tym samym adresem” - To całkowicie błędne. Tylko wyrażenia ciągów stałych w czasie kompilacji (możliwe, że obejmują final Stringzmienne) i ciągi, które Twój program jawnie internuje, są przechowywane w tak zwanej puli brył. Wszystkie inne Stringobiekty 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.
Ted Hopp,

Porównanie ciągów odbywa się za pomocą metody equals lub equalsIgnoreCase, która faktycznie porównuje zawartość ciągu. Ale == znak wystarczy sprawdzić wartości referencyjne. W przypadku literałów łańcuchowych z puli łańcuchów będzie działać dobrze w tym przypadku. Ciąg s1 = nowy Ciąg („a”); Ciąg s2 = nowy Ciąg („a”); w tym przypadku s1 == s2 jest fałszem, ale s1.equals (s2) jest prawdą.
Shailendra Singh,

39

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.


35

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.

Do ==kontroli operatora, jeśli dwa ciągi są dokładnie tego samego obiektu.

.equals()Check metoda, jeśli dwa ciągi mają tę samą wartość.


1
chyba że jeden z nich ma wartość NULL, ponieważ s.equals (s2) ulegnie awarii, jeśli s ma wartość NULL, co spowoduje niepowodzenie porównania. Oczywiście tak naprawdę nie przeczy to odpowiedzi; to tylko zastrzeżenie.
Jon Coombs,

1
Nie, to się nie zawiesi, zgłosi wyjątek NullPointerException, powodując, że porównanie się nie odbędzie.
Bludzee,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.