Относительно переопределения метода equals в java

Я пытался переопределить методы equals и hashcode в классе. Это подкласс другого класса, который не реализует методы equals и hashCode.

Eclipse дал следующее предупреждение.

  The super class ABC does not implement equals() and hashCode() methods.
  The resulting code may not work correctly. 

Почему дается вышеуказанное предупреждение? В каких случаях он может работать некорректно?


person Vinoth Kumar C M    schedule 19.10.2011    source источник
comment
Хороший обзор: artima.com/lejava/articles/equality.html   -  person Michael Brewer-Davis    schedule 19.10.2011


Ответы (2)


Если вы говорите a.equals(b) против b.equals(a), разумно ожидать, что поведение будет таким же. Но если они относятся к соответствующим типам B и A, связанным наследованием, и только один из них правильно реализует equals, то поведение в этих двух примерах будет разным.

Здесь A является суперклассом и вообще не реализует equals (поэтому он наследует java.lang.Object.equals). Подкласс B переопределяет equals, чтобы он зависел от поля name.

class A {

  String name;

  public A() {
    this.name = "Fred";
  }

}

class B extends A {

  public boolean equals(Object o) {
    A a = (A)o;
    return a != null && a.name.equals(this.name);
  }
}

public class Test {

  public static void main(String[] args) {

    A a = new A();
    B b = new B();

    System.out.println(a.equals(b) == b.equals(a));
  }
} 

Неудивительно, что на выходе будет false, поэтому нарушение симметрии.

person Daniel Earwicker    schedule 19.10.2011
comment
Я не согласен. Можете ли вы построить пример, в котором симметрия может быть нарушена, если суперкласс не реализует equals? Я совершенно уверен, что предупреждающее сообщение недействительно. Каждый пример нарушенной симметрии, который я видел, всегда требовал, чтобы суперкласс определял equals. - person Duncan Jones; 27.04.2013
comment
Ну не совсем. Почему метод equals в классе B приводит объект к A? Не поймите меня неправильно - вполне возможно создать пример, который нарушает симметрию, но каждый пример, который я видел, имеет (преднамеренно) серьезные ошибки. - person Duncan Jones; 29.04.2013
comment
(К вашему сведению, см. этот связанный вопрос: заголовок stackoverflow.com/questions/16236708/) - person Duncan Jones; 29.04.2013
comment
@DuncanJones - просто чтобы убедиться, что я не сойду с ума, вы все еще верите, что каждый пример нарушенной симметрии, который я видел, всегда требовал, чтобы суперкласс определял равенство? И относительно: Почему метод equals в классе B приводит объект к A, потому что начинающий программист хочет иметь возможность проверить равенство между B и A и, возможно, не очень тщательно все обдумал? Вот почему полезные инструменты сообщают вам, что вы сделали неправильно... - person Daniel Earwicker; 30.04.2013
comment
@DuncanJones. Из ваших комментариев по этому другому вопросу: У суперкласса нет метода equals. Так что ни один из ваших примеров не актуален. Все классы имеют метод equals - иногда они его наследуют, а иногда (поэтому) он неправильный. - person Daniel Earwicker; 30.04.2013
comment
Извините, я имел в виду, что суперкласс не отменяет равенство. - person Duncan Jones; 30.04.2013
comment
Что касается вашей первой проблемы - да, мне еще предстоит увидеть, что я считаю реальной проблемой симметрии, если только суперкласс не переопределяет равенство. Все классические примеры в литературе запускаются, когда суперкласс переопределяет равенство. - person Duncan Jones; 30.04.2013
comment
Вы утверждаете, что пример, который я привел, не мог произойти случайно или из-за непонимания новичка? Вот собственно и все эти предупреждения. - person Daniel Earwicker; 01.05.2013
comment
Нет, я думаю, что ваш пример может произойти. Я просто не уверен, что предупреждающее сообщение предназначено для начинающих, пишущих плохие методы equals, учитывая отсутствие советов, выдаваемых Eclipse в других сценариях. Я по-прежнему убежден, что это ошибочное сообщение, созданное кем-то, кто немного неправильно понимает литературу по этой теме. Мы никогда не узнаем наверняка, не спросив разработчиков — я могу сообщить об ошибке, чтобы вызвать дебаты. Я опубликую ссылку, если я делаю. - person Duncan Jones; 01.05.2013

Вы пробовали переопределить суперкласс равным... а затем автоматически сгенерировать реализацию переопределения подкласса...

Я уверен, что это будет по-другому. у него будет вызов super.equals()

в текущей автоматически сгенерированной реализации он проверяет только значения в дочернем классе.

Рассмотрим ниже сценарий, и вы поймете, почему предупреждение.

abstract Class A{
 private int a;
public void setA(int a){
this.a=a;
}
}

Class B extends A{
 private int x;
public void setX(int x){
this.x=x;
}

@Override
public boolean equals(Object obj) { // This does not call Super.equals
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    B other = (B) obj;
    if (x != other.x)
        return false;
    return true;
}

}

и в основном методе попробуйте

B b1= new B();
b1.setA(10);
b1.setX(20);


B b2= new B();
b2.setA(20);
b2.setX(20);

if(b1.equals(b2)){
 System.out.println("Warning was Right");
}
person rahul maindargi    schedule 26.04.2013