Сравните два объекта с помощью оператора .equals () и ==

85

Я построил класс с одним 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. Почему неверно, если два объекта имеют одинаковые поля - «тест»?

Fastkowy
источник
7
Кстати, глядя на equalsи equals2: каждый раз, когда у вас есть что-то в форме, 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 Crowder
источник
@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());
 }
user5119219
источник
2
Это, пожалуй, лучший ответ, однако вы можете использовать this.equals (obj) вместо (this == null) для непримитивных типов
goonerify
10
Я бы сказал, что в этом if (this == null)случае нет необходимости; вызов nullObject.equals(whatever)вызовет исключение нулевого указателя, поэтому мы можем с уверенностью предположить, что thisон не является нулевым в любом методе Java, который мы можем написать.
Маура
5

Похоже, equals2он просто звонит equals, поэтому даст те же результаты.

Хью Вольф
источник
1
OP вызывает equalsметод String, aкоторый является членом класса. equals2не звонитequals
Йигит Альпарслан
1
Да, спасибо. Похоже, я полностью упустил путаницу между MyClass и String, которая является настоящей проблемой.
Hew Wolff
5

Функция перезаписи equals () неверна. Объект «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 ツ
@Rolf ツ Почему, на ваш взгляд, это перебор? Я искал решение этой проблемы, и это самое простое решение, которое я нашел до сих пор. Любые лучшие предложения приветствуются.
m5seppal
3
Потому что с Java вы можете сравнивать объекты без предварительного создания Gsonобъекта, а затем вызова toJson. Создание Gsonобъекта и вызов логики, необходимой для преобразования фактического объекта в flat String( toJson), не требует дополнительных затрат. Вы можете сравнивать объекты без предварительного преобразования объектов в строки Json (что также быстрее).
Rolf ツ
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
}
Jlordo
источник
5
Justreturn a.equals(object2);
mojuba
2

Утверждения a == object2и a.equals(object2)оба всегда будут возвращаться, falseпотому что aэто stringвремя object2является экземпляромMyClass

ashish.al
источник
2

Ваша реализация должна нравиться:

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

С этой реализацией оба ваших метода будут работать.

Азхар Хан
источник
2

Если вам не нужно настраивать функцию toString () по умолчанию, другой способ - переопределить метод toString (), который возвращает все атрибуты для сравнения. затем сравните вывод toString () двух объектов. Я создал метод toString () с использованием IntelliJ IDEA IDE, который включает имя класса в строку.

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

Оператор «==» возвращает истину, только если две ссылки указывают на один и тот же объект в памяти. С другой стороны, метод 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

Ваш класс может реализовать интерфейс Comparable для достижения той же функциональности. Ваш класс должен реализовать метод 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");
        }
    }
}
tf3
источник
1

тип возвращаемого значения object.equals уже является логическим. нет необходимости оборачивать его методом с ветвями. поэтому, если вы хотите сравнить 2 объекта, просто сравните их:

boolean b = objectA.equals(objectB);

b уже либо истинно, либо ложно.

Cpt. Мирк
источник
1

Когда мы используем ==, сравнивается ссылка на объект, а не на реальные объекты. Нам нужно переопределить метод equals для сравнения объектов Java.

Некоторая дополнительная информация В C ++ есть оператор перегрузки, а в Java нет оператора перегрузки. Также другие возможности в java - это реализация интерфейса сравнения Который определяет метод compareTo.

Также используется интерфейс компаратора для сравнения двух объектов

Умеш Атада
источник
4
Учтите, что ваш ответ не добавляет ничего из того, о чем не было сказано почти 2 года назад.
Горячие лизания
1

Здесь вывод будет ложным, ложным, поскольку в первом операторе sopln вы пытаетесь сравнить переменную строкового типа типа Myclass с другим типом MyClass, и это позволит, поскольку оба являются типом объекта, и вы использовали оператор "==", который будет проверять значение ссылочной переменной, содержащее фактическую память, а не фактические элементы внутри памяти. Во втором sopln также это то же самое, что вы снова вызываете a.equals (object2), где a - переменная внутри объекта object1. Сообщите мне ваши выводы по этому поводу.

Бидьядхар
источник
2
Добро пожаловать в stackoverflow bidyadhar. Вопрос датирован 14.11.2012 и уже получил хороший ответ (одобрен OP). Тот, который у вас есть, правильный, но он не добавляет полезной информации. Я предлагаю вам прочитать правила, прежде чем что-либо делать
Никайдо
-3

В приведенном ниже коде вы вызываете переопределенный метод .equals ().

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

Баран
источник
1
Нет, a.equalsэто строковый метод, он нигде не отменяется.
Тарек