Порівняйте два об'єкти з операторами .equals () та ==


84

Я створив клас з одним Stringполем. Потім я створив два об’єкти, і я маю порівняти їх за допомогою ==оператора і .equals()теж. Ось що я зробив:

public class MyClass {

    String a;

    public MyClass(String ab) {
        a = ab;
    }

    public boolean equals(Object object2) {
        if(a == object2) { 
            return true;
        }
        else return false;
    }

    public boolean equals2(Object object2) {
        if(a.equals(object2)) {
            return true;
        }
        else return false;
    }



    public static void main(String[] args) {

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        object1.equals(object2);
        System.out.println(object1.equals(object2));

        object1.equals2(object2);
        System.out.println(object1.equals2(object2));
    }


}

Після компіляції в результаті він показує два рази false. Чому неправда, якщо два об'єкти мають однакові поля - "тест"?


7
До речі, дивлячись equalsequals2 : і в будь-який час у вас є щось із форми, if(a) { return true; } else { return false; }яку ви, мабуть, просто повинні написати return a.
yshavit

@yshavit Ви маєте на увазі, зі зміною з логічного на String?
Fastkowy

4
ні, ваш код запитує, чи логічне значення є істинним, і повертає, trueякщо це так, falseінакше. Так, наприклад, if(a.equals(object2)) { return true; } else return falseможе бути просто return a.equals(object2).
yshavit

1
можливий дублікат Як порівняти рядки в Java?
bjb568,

Відповіді:


142

==порівнює посилання на об'єкти, перевіряє, чи вказують два операнди на один і той же об'єкт (не еквівалентні об'єкти, той самий об'єкт).

Якщо ви хочете порівняти рядки (щоб перевірити, чи містять вони однакові символи), вам потрібно порівняти рядки за допомогою equals.

У вашому випадку, якщо два екземпляри MyClassдійсно вважаються рівними, якщо рядки збігаються, тоді:

public boolean equals(Object object2) {
    return object2 instanceof MyClass && a.equals(((MyClass)object2).a);
}

... але зазвичай, якщо ви визначаєте клас, до еквівалентності належить більше, ніж еквівалентність окремого поля ( aу цьому випадку).


Примітка: Якщо ви перевизначите equals , вам майже завжди потрібно перевизначити hashCode. Як сказано в equalsJavaDoc :

Зауважте, що загалом необхідно замінювати hashCodeметод щоразу, коли цей метод замінений, щоб підтримувати загальний контракт для hashCodeметоду, який стверджує, що рівні об'єкти повинні мати однакові хеш-коди.


@TJ In == порівнює посилання на об'єкти, щоб уточнити, чи означає це == порівнює хеш-код двох об'єктів?
Нарендра Джаггі

@NarendraJaggi - Ні, це означає, що JVM перевіряє, чи обидва операнди посилаються на один і той же об'єкт. Як це робити, залежить від JVM, але немає підстав думати, що для цього він використовував би хеш-код.
TJ Crowder

19

Ви повинні замінити рівне

 public boolean equals (Object obj) {
     if (this==obj) return true;
     if (this == null) return false;
     if (this.getClass() != obj.getClass()) return false;
     // Class name is Employ & have lastname
     Employe emp = (Employee) obj ;
     return this.lastname.equals(emp.getlastname());
 }

2
Це, мабуть, найкраща відповідь, однак ви можете використовувати this.equals (obj) замість (this == null) для не примітивних типів
goonerify

10
Я б стверджував, що if (this == null)справа все одно непотрібна; виклик nullObject.equals(whatever)викличе нульовий виняток покажчика, тому ми можемо сміливо припустити, що thisне є нульовим у будь-якому методі Java, який ми можемо писати.
Маура

1
це не вдасться, якщо this має значення lastnamenull і не відповідає попереднім умовам.
Ахмед Раадж

5

Схоже, equals2це просто дзвінок equals, тож це дасть ті самі результати.


1
OP викликає equalsметод String, aякий є членом класу. equals2не телефонуєequals
Ігіт Альпарслан

Так дякую. Схоже, я повністю пропустив плутанину між MyClass і String, що є справжньою проблемою.
Хью Вольф

5

Функція перезапису дорівнює () неправильна. Об'єкт "a" є екземпляром класу String, а "object2" є екземпляром класу MyClass . Це різні класи, тому відповідь «помилковий».


5

Найкращий спосіб порівняти 2 об’єкти - це перетворити їх на json-рядки та порівняти рядки, що є найпростішим рішенням при роботі зі складними вкладеними об’єктами, полями та / або об’єктами, що містять масиви.

зразок:

import com.google.gson.Gson;


Object a = // ...;
Object b = //...;
String objectString1 = new Gson().toJson(a);
String objectString2 = new Gson().toJson(b); 

if(objectString1.equals(objectString2)){
    //do this
}

9
Я хотів би назвати це: надмірне.
Рольф ツ

@Rolf ツ Чому це, на вашу думку, надмірне? Я шукав рішення цієї проблеми, і це найпростіше рішення, яке я знайшов на даний момент. Будь-які кращі пропозиції вітаються.
m5seppal

3
Оскільки за допомогою Java ви можете порівнювати об’єкти, не створюючи спочатку Gsonоб’єкт, а потім викликаючи toJson. Створення Gsonоб'єкта та виклик логіки, необхідної для перетворення фактично об'єкта в flat String( toJson), є зайвими накладними витратами. Ви можете порівнювати об'єкти без попереднього перетворення об'єктів у рядки Json (що також швидше).
Рольф ツ

3

Ваш equals2()метод завжди повертає те саме, що іequals() !!

Ваш код із моїми коментарями:

public boolean equals2(Object object2) {  // equals2 method
    if(a.equals(object2)) { // if equals() method returns true
        return true; // return true
    }
    else return false; // if equals() method returns false, also return false
}

5
Простоreturn a.equals(object2);
моджуба

2

Заяви a == object2і a.equals(object2)обидва вони завжди повертатимуться, falseтому що aa stringwhile object2є екземпляромMyClass


2

Ваша реалізація повинна сподобатися:

public boolean equals2(Object object2) {
    if(a.equals(object2.a)) {
        return true;
    }
    else return false;
}

З цією реалізацією обидва методи працювали б.


2

Якщо вам не потрібно налаштовувати функцію toString () за замовчуванням, іншим способом є перевизначення методу toString (), який повертає всі атрибути для порівняння. потім порівняйте вивід двох об'єктів toString (). Я створив метод toString (), використовуючи IDE IDE IntelliJ, який включає ім'я класу в рядок.

public class Greeting {
private String greeting;

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    return this.toString().equals(obj.toString());
}

@Override
public String toString() {
    return "Greeting{" +
            "greeting='" + greeting + '\'' +
            '}';
}
}

2

Оператор "==" повертає значення true, лише якщо два посилання, що вказують на той самий об'єкт у пам'яті. З іншого боку, метод equals () повертає true на основі вмісту об'єкта.

Приклад:

String personalLoan = new String("cheap personal loans");
String homeLoan = new String("cheap personal loans");

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

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

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

Вихідні дані: Порівняння двох рядків з оператором ==: false Порівняння двох рядків з однаковим вмістом за допомогою методу equals: true Порівняння двох посилань, що вказують на один і той же рядок, з оператором ==: true

Ви також можете отримати докладнішу інформацію за посиланням: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1


2

Ваш клас може застосувати порівняльний інтерфейс для досягнення тієї ж функціональності. Ваш клас повинен реалізувати метод compareTo (), оголошений в інтерфейсі.

public class MyClass implements Comparable<MyClass>{

    String a;

    public MyClass(String ab){
        a = ab;
    }

    // returns an int not a boolean
    public int compareTo(MyClass someMyClass){ 

        /* The String class implements a compareTo method, returning a 0 
           if the two strings are identical, instead of a boolean.
           Since 'a' is a string, it has the compareTo method which we call
           in MyClass's compareTo method.
        */

        return this.a.compareTo(someMyClass.a);

    }

    public static void main(String[] args){

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        if(object1.compareTo(object2) == 0){
            System.out.println("true");
        }
        else{
            System.out.println("false");
        }
    }
}

1

тип повернення object.equals вже логічний. немає необхідності обертати його методом з гілками. так що якщо ви хочете порівняти 2 об’єкти, просто порівняйте їх:

boolean b = objectA.equals(objectB);

b вже є або true, або false.


1

Коли ми використовуємо ==, посилання на об'єкт порівнюється не з реальними об'єктами. Нам потрібно замінити метод equals для порівняння Java Objects.

Деяка додаткова інформація C ++ має оператор при завантаженні, а Java не надає оператора при завантаженні. Також інші можливості в Java реалізують інтерфейс порівняння. Який визначає метод compareTo.

Порівняльний інтерфейс також використовується для порівняння двох об'єктів


4
Вважайте, що ваша відповідь не додає нічого, що не було сказано майже 2 роки тому.
Hot Licks

1

Тут результат буде хибним, помилковим, оскільки в першому операторі sopln ви намагаєтеся порівняти змінну типу рядка типу Myclass з іншим типом MyClass, і це дозволить, оскільки обидва вони є типом Object, і ви використовували "==" oprerator, який перевірятиме значення опорної змінної, що містить фактичну пам’ять, а не фактичні коннети у пам’яті. У другому sopln це теж саме, що ви знову викликаєте a.equals (object2), де a є змінною всередині object1. Повідомте мене про ваші висновки з цього приводу.


2
Ласкаво просимо до stackoverflow bidyadhar. Питання датоване 14.11.2012 р. І вже отримало добру відповідь (затверджено ОП). Той, який ви отримали, правильний, але він не додає корисної інформації. Я пропоную вам прочитати правила, перш ніж що-небудь робити
Нікайдо

-3

У наведеному нижче коді ви викликаєте метод overriden .equals ().

public boolean equals2 (Object object2) {if (a.equals (object2)) {// тут ви викликаєте метод overriden, тому ви отримуєте false 2 рази. повернути істинно; } else повертає false; }


1
Ні, a.equalsце метод рядка, він ніде не замінений.
Тарек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.