Jaka jest różnica między == a equals () w Javie?

622

Chciałem wyjaśnić, czy dobrze to rozumiem:

  • == jest porównaniem odniesienia, tzn. oba obiekty wskazują to samo miejsce w pamięci
  • .equals() ocenia do porównania wartości w obiektach
brainydexter
źródło
43
tak, właściwie
John Kane,
9
Tak, natychmiast. Można myśleć .equals()jak sensownie odpowiednik
vikingsteve
Możliwy duplikat Jak porównać ciągi w Javie?
TylerH
19
Zdanie takie jak „oba obiekty wskazują na to samo miejsce w pamięci” jest niedbałym językiem, co może utrudnić zrozumienie. Masz na myśli: „obie zmienne odnoszą się do tego samego obiektu”. Zauważ, że zmienna nie jest obiektem; zmienna jest odwołaniem do obiektu. Obiekty niczego nie „wskazują”.
Jesper

Odpowiedzi:

625

Zasadniczo odpowiedź na twoje pytanie brzmi „tak”, ale ...

  • .equals(...) porówna tylko to, co napisano do porównania, nie więcej, nie mniej.
  • Jeśli klasa nie przesłania metody równości, wówczas domyślnie jest to equals(Object o)metoda najbliższej klasy nadrzędnej, która zastąpiła tę metodę.
  • Jeśli żadna klasa nadrzędna nie zapewniła zastąpienia, wówczas domyślnie jest to metoda z najwyższej klasy nadrzędnej, Object, więc pozostaje ci Object#equals(Object o)metoda. Dla interfejsu API obiektu jest to to samo, co ==; to znaczy zwraca prawdę wtedy i tylko wtedy, gdy obie zmienne odnoszą się do tego samego obiektu, jeśli ich odwołania są takie same. W ten sposób będziesz testować równość obiektów, a nie równość funkcjonalną .
  • Zawsze pamiętaj o nadpisaniu, hashCodejeśli nadpisujesz, equalsaby nie „zerwać kontraktu”. Zgodnie z interfejsem API wynik zwracany z hashCode()metody dla dwóch obiektów musi być taki sam, jeśli ich equalsmetody wykazują, że są one równoważne. Odwrotna sytuacja nie musi być prawdą.
Poduszkowiec pełen węgorzy
źródło
jeśli ==sprawdza referencje pamięci, to dlaczego otrzymuję to dziwne zachowanie w [this] [1] [1]: docs.google.com/document/d/… Spodziewałem się, że dane wyjściowe będą prawdziwe. mogę usunąć moje nieporozumienia
JPG
4
@JSK wydrukuj wartości d1 i d2 i myślę, że zobaczysz, dlaczego zwracasz wartość false.
BoDidely,
2
@ BooDidely to rozgryzłem. Stało się tak, ponieważ wszystkie klasy opakowań są niezmienne.
JPG
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).<br/> Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.( docs.oracle.com/javase/7/docs/api/java/lang/… )
Abhijeet
Niepowiązane: Dzisiaj zadaję meta pytanie ( meta.stackoverflow.com/questions/372795 /...) dotyczące dobrych / skutecznych / ... automatycznych wiadomości podczas komentowania niskiej jakości pytań dla początkujących. Informacje zwrotne, które otrzymałem, brzmiały w zasadzie „robisz coś zupełnie złego”. Teraz po prostu zastanawiam się, jak na to patrzysz? Czy masz w swoim kołczanie „ogólne” wiadomości, czy w takich przypadkach piszesz wyłącznie konkretne komentarze?
GhostCat,
107

W odniesieniu do klasy String:

Równości () Sposób porównuje „wartość” wewnątrz przypadkach łańcuch znaków (na hałdy), niezależnie, czy dwa odniesienia obiektów odnoszą się do tego samego przykładu łańcuchach lub nie. Jeśli jakieś dwa odwołania do obiektów typu String odnoszą się do tej samej instancji String, to świetnie! Jeśli dwa odwołania do obiektów odnoszą się do dwóch różnych instancji String ... nie robi to różnicy. Jest to „wartość” (to znaczy zawartość tablicy znaków) w każdej porównywanej instancji String.

Z drugiej strony operator „==” porównuje wartość dwóch odwołań do obiektów, aby sprawdzić, czy odnoszą się one do tej samej instancji String . Jeśli wartość obu odwołań do obiektów „odnosi się” do tej samej instancji String, wynikiem wyrażenia logicznego byłoby „true” .. duh. Jeśli natomiast wartość obu odwołań do obiektów „odnosi się” do różnych instancji String (mimo że obie instancje String mają identyczne „wartości”, to znaczy zawartość tablic znaków każdej instancji String jest taka sama), wynikiem wyrażenia logicznego byłoby „fałsz”.

Jak w przypadku każdego wyjaśnienia, pozwól mu się zanurzyć.

Mam nadzieję, że to trochę wyjaśni.

Jacques Colmenero
źródło
1
więc dla ciągów == czy odwołanie jest równe? tzn. działa tak samo jak w przypadku innych obiektów?
JonnyRaa
2
(Wiem, że nekromancja wątku ...) Dla Strings, ==odniesienie jest również równe, tak, ale zwykle działa (jak w dwóch Stringsekundach z tą samą zawartością zwykle będą ==do siebie), z powodu tego, jak Java obsługuje Strings. Nie zawsze będzie to z pewnością zła praktyka, ale jest to powszechny błąd, szczególnie wśród osób pochodzących z innych języków.
Tonio
7
Aby dodać do komentarza Tonio. Stringbuild z literału łańcuchowego zostanie dodany do czegoś zwanego String constant poolnp. String s1 = "someString"; String s2 = "someString;"oba s1i s2będą dzielić to samo odwołanie. s1 == s2zwróci prawdę. Ale jeśli zostały zbudowane String constructornp. String s1 = new String("someString"); String s2 = new String("someString");, To nie będą dzielić tego samego odniesienia. s1 == s2zwróci fałsz.
Gavin
61

Istnieją niewielkie różnice w zależności od tego, czy mówimy o „prymitywach”, czy „typach obiektów”; to samo można powiedzieć, jeśli mówimy o członkach „statycznych” lub „niestatycznych”; możesz także wymieszać wszystkie powyższe ...

Oto przykład (możesz go uruchomić):

public final class MyEqualityTest
{
    public static void main( String args[] )
    {
        String s1 = new String( "Test" );
        String s2 = new String( "Test" );

        System.out.println( "\n1 - PRIMITIVES ");
        System.out.println( s1 == s2 ); // false
        System.out.println( s1.equals( s2 )); // true

        A a1 = new A();
        A a2 = new A();

        System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
        System.out.println( a1 == a2 ); // false
        System.out.println( a1.s == a2.s ); // true
        System.out.println( a1.s.equals( a2.s ) ); // true

        B b1 = new B();
        B b2 = new B();

        System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
        System.out.println( b1 == b2 ); // false
        System.out.println( b1.getS() == b2.getS() ); // false
        System.out.println( b1.getS().equals( b2.getS() ) ); // true
    }
}

final class A
{
    // static
    public static String s;
    A()
    {
        this.s = new String( "aTest" );
    }
}

final class B
{
    private String s;
    B()
    {
        this.s = new String( "aTest" );
    }

    public String getS()
    {
        return s;
    }

}

Możesz porównać objaśnienia dla „==” (operator równości) i „.equals (...)” (metoda w klasie java.lang.Object) za pomocą tych łączy:

Almir Campos
źródło
2
Ciekawy przykład Inne spojrzenie z powyższych odpowiedzi. Dzięki!
Andrew
1
Moim zdaniem najlepsza odpowiedź, ponieważ jest jaśniejsza niż inne odpowiedzi pełnotekstowe bez utraty wyjaśnienia (oczywiście jeśli
przyjmiesz
44

Różnica między == i równa mi się przez jakiś czas myliła, dopóki nie zdecydowałem się przyjrzeć jej bliżej. Wielu z nich twierdzi, że do porównywania ciągów powinieneś używać, equalsa nie używać== . Mam nadzieję, że w tej odpowiedzi będę mógł powiedzieć różnicę.

Najlepszym sposobem na udzielenie odpowiedzi na to pytanie będzie zadanie sobie kilku pytań. a więc zacznijmy:

Jakie są dane wyjściowe dla poniższego programu:

String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);

Jeśli powiesz,

false
true

Powiem, że masz rację, ale dlaczego to powiedziałeś ? a jeśli powiesz, że wynik jest

true
false

Powiem, że się mylisz, ale wciąż będę cię pytać, dlaczego uważasz, że tak jest?

Ok, spróbujmy odpowiedzieć na to:

Jakie są dane wyjściowe dla poniższego programu:

String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);

Teraz, jeśli powiesz,

false
true

Powiem, że się mylisz, ale dlaczego teraz się mylisz ? poprawne wyjście dla tego programu to

true
false

Porównaj powyższy program i spróbuj o tym pomyśleć.

Ok. Teraz to może pomóc (przeczytaj to: wydrukuj adres obiektu - nie jest to możliwe, ale nadal możemy go używać).

String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);

System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));

czy możesz po prostu pomyśleć o wynikach trzech ostatnich wierszy powyższego kodu: dla mnie ideone wydrukował to ( możesz sprawdzić kod tutaj ):

false
true
true
false
mango mango
false
true
17225372
17225372
5433634

O! Teraz widzisz tożsamośćHashCode (mango) jest równa identycznościHashCode (mango2) Ale nie jest równa identycznościHashCode (mango3)

Mimo że wszystkie zmienne łańcuchowe - mango, mango2 i mango3 - mają tę samą wartość, czyli „mango”,identityHashCode() nadal nie jest taka sama dla wszystkich.

Teraz spróbuj odkomentować tę linię // mango2 = "mang";i uruchom ją ponownie, tym razem zobaczysz wszystkie trzyidentityHashCode() są różne. Hmm, to jest przydatna wskazówka

wiemy, że jeśli hashcode(x)=Nihashcode(y)=N =>x is equal to y

Nie jestem pewien, jak java działa wewnętrznie, ale zakładam, że tak się stało, kiedy powiedziałem:

mango = "mango";

java utworzyła ciąg, "mango"który został wskazany (przywołany) przez zmienną mangocoś takiego

mango ----> "mango"

Teraz w następnym wierszu, kiedy powiedziałem:

mango2 = "mango";

W rzeczywistości użył ponownie tego samego ciągu, "mango"który wygląda mniej więcej tak

mango ----> "mango" <---- mango2

Zarówno mango, jak i mango2 wskazują na to samo odniesienie Teraz, kiedy powiedziałem

mango3 = new String("mango")

W rzeczywistości stworzył zupełnie nowe odniesienie (ciąg znaków) dla „mango”. który wygląda mniej więcej tak

mango -----> "mango" <------ mango2

mango3 ------> "mango"

i dlatego, gdy podałem wartości dla mango == mango2, to zgasło true. a kiedy wyłożyłem wartość mango3 == mango2, zgasłofalse (nawet gdy wartości są takie same).

a kiedy odkomentowałeś linię, // mango2 = "mang"; faktycznie utworzył ciąg „mang”, który zmienił nasz wykres w ten sposób:

mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"

To dlatego identyfikator tożsamości nie jest taki sam dla wszystkich.

Mam nadzieję, że to wam pomoże. Właściwie chciałem wygenerować przypadek testowy, w którym == kończy się niepowodzeniem i równa się () przejściu. Skomentuj i daj mi znać, jeśli się mylę.

govindpatel
źródło
Czy mango == mango2dzieje się tak, ponieważ nie utworzono mango2 nowego obiektu String, a zamiast tego bezpośrednio się do niego odwołuje "mango"?
brt
1
niewłaściwy przykład użycia ciągu do wyjaśnienia wątpliwości = = i równa się, ciąg nieużywany z nowym jest umieszczany w puli ciągów i za każdym razem, gdy ten sam ciąg jest przypisywany do nowego odwołania, wskazuje ten sam ciąg w puli. Prawdopodobnie więc skorzystaj z przykładu niestandardowego obiektu do porównania == i .equals ().
om252345
30

W == testy operatorskie czy dwie zmienne mają takie same oznaczenia (aka wskaźnik do adresu pamięci) .

String foo = new String("abc");
String bar = new String("abc");

if(foo==bar)
// False (The objects are not the same)

bar = foo;

if(foo==bar)
// True (Now the objects are the same)

Natomiast metoda equals () sprawdza, czy dwie zmienne odnoszą się do obiektów o tym samym stanie (wartościach) .

String foo = new String("abc");
String bar = new String("abc");

if(foo.equals(bar))
// True (The objects are identical but not same)

Twoje zdrowie :-)

Mohanraj Balasubramaniam
źródło
1
Źle. if (foo == bar) to powinna być prawda, a nie fałsz. Ponownie użyje tego samego ciągu „adc”. Przetestuj w piaskownicy, zwróci prawdę dla obu.
Johnathan Logan,
2
@JohnathanLogan Myślę, że to z powodu internowania strun. Teraz zmieniłem na „nowy ciąg („ abc ”)”. Mam nadzieję, że teraz nie będzie żadnych problemów. Dziękuję za informację.
Mohanraj Balasubramaniam
13

Będziesz musiał zastąpić funkcję równości (wraz z innymi), aby użyć jej z niestandardowymi klasami.

Metoda równa porównuje obiekty.

==Operatora binarnego porównuje adresy pamięci.

Andrew Carr
źródło
8

Zarówno ==, jak i .equals () odnoszą się do tego samego obiektu, jeśli nie zastąpisz .equals ().

To jest twoje życzenie, co chcesz zrobić, gdy zastąpisz .equals (). Możesz porównać stan obiektu wywołującego ze stanem obiektu przekazanego lub możesz po prostu wywołać super.equals ()

tintin
źródło
7

==jest operatorem i equals()jest metodą .

Operatory są zwykle używane do pierwotnych porównań typów, dlatego ==są używane do porównywania adresów pamięci, a equals()metoda służy do porównywania obiektów .

Ayniam
źródło
6
 String w1 ="Sarat";
 String w2 ="Sarat";
 String w3 = new String("Sarat");

 System.out.println(w1.hashCode());   //3254818
 System.out.println(w2.hashCode());   //3254818
 System.out.println(w3.hashCode());   //3254818

 System.out.println(System.identityHashCode(w1)); //prints 705927765
 System.out.println(System.identityHashCode(w2)); //prints 705927765
 System.out.println(System.identityHashCode(w3)); //prints 366712642


 if(w1==w2)   //  (705927765==705927765)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true

 if(w2==w3)   //  (705927765==366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints false


 if(w2.equals(w3))   //  (Content of 705927765== Content of 366712642)
 {
   System.out.println("true");
 }
 else
 {
   System.out.println("false");
 }
 //prints true
Sarat Chandra
źródło
Proste i najlepsze wyjaśnienie
Sritam Jagadev
5

Pamiętaj tylko, że .equals(...)musi to zostać zaimplementowane przez klasę, którą próbujesz porównać. W przeciwnym razie nie ma większego sensu; wersja metody dla klasy Object robi to samo, co operacja porównania: Object # jest równy .

Jedynym momentem, w którym naprawdę chcesz użyć operatora porównania dla obiektów, jest porównanie Enums. Jest tak, ponieważ istnieje tylko jedna instancja wartości Enum na raz. Na przykład biorąc pod uwagę wyliczenie

enum FooEnum {A, B, C}

Nigdy nie będziesz mieć więcej niż jednego wystąpienia Anaraz i to samo dla Bi C. Oznacza to, że możesz napisać taką metodę:

public boolean compareFoos(FooEnum x, FooEnum y)
{
    return (x == y);
}

I nie będziesz mieć żadnych problemów.

fruchtose
źródło
4

Kiedy oceniasz kod, jest bardzo jasne, że (==) porównuje według adresu pamięci, podczas gdy equals (Object o) porównuje hashCode () instancji. Dlatego mówi się, aby nie łamać umowy między equals () i hashCode (), jeśli później nie spotka Cię niespodzianka.

    String s1 = new String("Ali");
    String s2 = new String("Veli");
    String s3 = new String("Ali");

    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
    System.out.println(s3.hashCode());


    System.out.println("(s1==s2):" + (s1 == s2));
    System.out.println("(s1==s3):" + (s1 == s3));


    System.out.println("s1.equals(s2):" + (s1.equals(s2)));
    System.out.println("s1.equal(s3):" + (s1.equals(s3)));


    /*Output 
    96670     
    3615852
    96670
    (s1==s2):false
    (s1==s3):false
    s1.equals(s2):false
    s1.equal(s3):true
    */
huseyin
źródło
4

Oto ogólna zasada dotycząca różnicy między relational operator ==i the method .equals().

object1 == object2porównuje, czy obiekty, do których odwołują się obiekty object1 i object2, odnoszą się do tej samej lokalizacji pamięci w Heap .

object1.equals(object2)porównuje wartości object1 i object2 niezależnie od tego, gdzie znajdują się w pamięci .

Można to dobrze zademonstrować za pomocą String

Scenariusz 1

 public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = new String("Hello");
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

 }



The result is
      is str1 == str2 ? false
      is str1.equals(str2) ? true 

Scenariusz 2

public class Conditionals {

    public static void main(String[] args) {
       String str1 = "Hello";
       String str2 = "Hello";
       System.out.println("is str1 == str2 ? " + (str1 == str2 ));
       System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
    }

}

The result is 
  is str1 == str2 ? true
  is str1.equals(str2) ? true

To porównanie ciągów może być wykorzystane jako podstawa do porównania innych typów obiektów.

Na przykład, jeśli mam klasę Person , muszę zdefiniować podstawę kryteriów, na podstawie której porównam dwie osoby . Powiedzmy, że ta klasa osób ma zmienne instancji wzrostu i wagi.

Więc tworząc obiekty osoby person1 and person2i porównując te dwa za pomocą .equals()I, muszę przesłonić metodę równości klasy person aby zdefiniować na podstawie zmiennych instancji (wysokość lub waga), jakie będzie porównanie.

Jednak == operator will still return results based on the memory location of the two objects(person1 and person2).

Dla ułatwienia uogólnienia porównania obiektów tej osoby stworzyłem następującą klasę testową. Eksperymentowanie z tymi koncepcjami ujawni mnóstwo faktów .

package com.tadtab.CS5044;

public class Person {

private double height;
private double weight;

public double getHeight() {
    return height;
}

public void setHeight(double height) {
    this.height = height;
}

public double getWeight() {
    return weight;
}

public void setWeight(double weight) {
    this.weight = weight;
}


@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(height);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    return result;
}

@Override
/**
 * This method uses the height as a means of comparing person objects.
 * NOTE: weight is not part of the comparison criteria
 */
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Person other = (Person) obj;
    if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
        return false;
    return true;
}

public static void main(String[] args) {

    Person person1 = new Person();
    person1.setHeight(5.50);
    person1.setWeight(140.00);

    Person person2 = new Person();
    person2.setHeight(5.70);
    person2.setWeight(160.00);

    Person person3 = new Person();
    person3 = person2;

    Person person4 = new Person();
    person4.setHeight(5.70);

    Person person5 = new Person();
    person5.setWeight(160.00);

    System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
    System.out.println("is person2 == person3 ? " + (person2 == person3)); // true 
    //this is because perosn3 and person to refer to the one person object in memory. They are aliases;
    System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;

    System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;

    // even if the person2 and person5 have the same weight, they are not equal.
    // it is because their height is different
    System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}

}

Wynikiem wykonania tej klasy jest:

is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
Tadele Ayelegn
źródło
3

Zauważ też, że .equals()zwykle zawiera== do testowania, ponieważ jest to pierwsza rzecz, którą chcesz przetestować, jeśli chcesz sprawdzić, czy dwa obiekty są równe.

I ==faktycznie sprawdza wartości dla typów pierwotnych, dla obiektów sprawdza referencje.

bfs
źródło
3

== operator zawsze porównuje odniesienie. Ale w przypadku

metoda równa się ()

to zależy od implementacji, jeśli mamy przesłoniętą metodę równości, niż porównuje obiekt z podstawową implementacją podaną w przesłoniętej metodzie.

 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//fasle
      obj==obj1 // fasle
    }
 }

w powyższym kodzie zarówno obiekt obj, jak i obiekt obj1 zawierają te same dane, ale odwołanie nie jest takie samo, więc równa się również false i ==. ale jeśli zastąpimy metodę równa się niż

 class A
 {
   int id;
   String str;

     public A(int id,String str)
     {
       this.id=id;
       this.str=str;
     }
    public boolean equals(Object obj)
    {
       A a1=(A)obj;
      return this.id==a1.id;
    }

    public static void main(String arg[])
    {
      A obj=new A(101,"sam");
      A obj1=new A(101,"sam");

      obj.equals(obj1)//true
      obj==obj1 // fasle
    }
 }

Wiem, sprawdź, zwróci prawdę i fałsz w tym samym przypadku tylko my zastąpiliśmy

równa się metoda.

porównuje obiekt na podstawie podstawowej treści (id) obiektu

ale ==

nadal porównuj odniesienia do obiektu.

Sachin Jadhav
źródło
3

Główną różnicą między == a equals () jest

1) == służy do porównywania prymitywów.

Na przykład :

        String string1 = "Ravi";
        String string2 = "Ravi";
        String string3 = new String("Ravi");
        String string4 = new String("Prakash");

        System.out.println(string1 == string2); // true because same reference in string pool
        System.out.println(string1 == string3); // false

2) equals () służy do porównywania obiektów. Na przykład :

        System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects
        System.out.println(string1.equals(string3)); // true
        System.out.println(string1.equals(string4)); // false
Ravi Patel
źródło
2

==można go używać w wielu typach obiektów, ale można go używać Object.equalsw dowolnym typie, zwłaszcza w ciągach znaków i znacznikach mapy Google.

Dearwolves
źródło
2
public class StringPool {

public static void main(String[] args) {

    String s1 = "Cat";// will create reference in string pool of heap memory
    String s2 = "Cat";
    String s3 = new String("Cat");//will create a object in heap memory

    // Using == will give us true because same reference in string pool

    if (s1 == s2) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using == with reference and Object will give us False

    if (s1 == s3) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    // Using .equals method which refers to value

    if (s1.equals(s3)) {
        System.out.println("true");
    } else {
        System.out.println("False");
    }

    }
  }

---- Wyjście ----- prawda fałsz prawda

Aamir M. Meman
źródło
2

Warto dodać, że dla obiektów otoki dla typów pierwotnych - tj. Int, Long, Double - == zwróci true, jeśli obie wartości są równe.

Long a = 10L;
Long b = 10L;

if (a == b) {
    System.out.println("Wrapped primitives behave like values");
}

Dla kontrastu, umieszczenie powyższych dwóch Longów w dwóch oddzielnych ArrayLists, równa się, widzi je tak samo, ale == nie.

ArrayList<Long> c = new ArrayList<>();
ArrayList<Long> d = new ArrayList<>();

c.add(a);
d.add(b);
if (c == d) System.out.println("No way!");
if (c.equals(d)) System.out.println("Yes, this is true.");
Elroch
źródło
Obiekty opakowania dla typów pierwotnych - tj. Liczba całkowita, Długa, Podwójna == mogą nie zwracać wartości true, nawet jeśli dwie wartości są równe. To zależy wyłącznie od pamięci podręcznej Wrappera. Poniższy kod wypisze fałsz, ponieważ domyślna pamięć podręczna jest ograniczona do -128 do 127. Long a = 128l; Long b = 128l; System.out.println(a == b);
Neetesh Bhardwaj
1

Basen String (aka interning ) i basen Integer rozmycie różnica dalej, i może pozwolić na wykorzystanie ==obiektów w niektórych przypadkach zamiast.equals

Może to zapewnić większą wydajność (?), Kosztem większej złożoności.

Na przykład:

assert "ab" == "a" + "b";

Integer i = 1;
Integer j = i;
assert i == j;

Kompromis złożoności: mogą Cię zaskoczyć:

assert new String("a") != new String("a");

Integer i = 128;
Integer j = 128;
assert i != j;

Radzę trzymać się z dala od takiej mikrooptymalizacji i zawsze używać .equalsdo obiektów i ==do prymitywów:

assert (new String("a")).equals(new String("a"));

Integer i = 128;
Integer j = 128;
assert i.equals(j);
Ciro Santilli
źródło
1

Krótko mówiąc, odpowiedź brzmi „tak”.

W Javie ==operator porównuje dwa obiekty, aby sprawdzić, czy wskazują one na tę samą lokalizację pamięci; podczas gdy .equals()metoda faktycznie porównuje dwa obiekty, aby sprawdzić, czy mają taką samą wartość obiektu.

JamesOstmann
źródło
0

Zasadniczo ==porównuje, jeśli dwa obiekty mają to samo odwołanie na stercie, więc jeśli dwa odniesienia nie zostaną połączone z tym samym obiektem, to porównanie będzie fałszywe.

equals()jest metodą odziedziczoną z Objectklasy. Ta metoda domyślnie porównuje, jeśli dwa obiekty mają to samo odniesienie. To znaczy:

object1.equals(object2) <=> object1 == object2

Jeśli jednak chcesz ustalić równość między dwoma obiektami tej samej klasy, powinieneś przesłonić tę metodę. Bardzo ważne jest również przesłonięcie metody, hashCode()jeśli przesłoniłeśequals() .

Wdrażaj, hashCode()gdy ustalanie równości jest częścią umowy Java Object Contract. Jeśli pracujesz z kolekcjami, a nie wdrożyłeś hashCode(), mogą się zdarzyć dziwne złe rzeczy:

HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat, "This is a cool cat");
System.out.println(cats.get(new Cat("molly"));

nullzostanie wydrukowany po wykonaniu poprzedniego kodu, jeśli nie został zaimplementowany hashCode().

lmiguelvargasf
źródło
0

Ponieważ Java nie obsługuje przeciążania operatorów, == zachowuje się identycznie dla każdego obiektu, ale equals () jest metodą, którą można zastąpić w Javie, a logikę porównywania obiektów można zmieniać w oparciu o reguły biznesowe.

Główną różnicą między == i equals w Javie jest to, że „==” służy do porównywania prymitywów, a metoda equals () jest zalecana do sprawdzania równości obiektów.

Porównanie ciągów jest częstym scenariuszem używania metody == i równości. Ponieważ przesłonięcie klasy java.lang.String jest równe metodzie, Zwraca true, jeśli dwa obiekty String zawierają tę samą treść, ale == zwróci true tylko wtedy, gdy dwa odwołania wskazują na ten sam obiekt.

Oto przykład porównania dwóch ciągów w Javie pod kątem równości za pomocą metody == i equals (), które rozwieją pewne wątpliwości:

public class TEstT{

    public static void main(String[] args) {

String text1 = new String("apple");
String text2 = new String("apple");

//since two strings are different object result should be false
boolean result = text1 == text2;
System.out.println("Comparing two strings with == operator: " + result);

//since strings contains same content , equals() should return true
result = text1.equals(text2);
System.out.println("Comparing two Strings with same content using equals method: " + result);

text2 = text1;
//since both text2 and text1d reference variable are pointing to same object
//"==" should return true
result = (text1 == text2);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);

}
}
Mike Clark
źródło