Метод Equals для объектов

Я пытаюсь написать метод equals для объектов, который сравнивает их поля и возвращает true, если они равны.

private int x, y, direction;
private Color color;

public boolean equals(Ghost other){
   if (this.x == other.x && this.y == other.y &&
       this.direction == other.direction && this.color == other.color)
      return true;
   else 
      return false;
}

Что может быть не так с этим?


person Snowman    schedule 16.10.2010    source источник
comment
@fprime: вам нужен только один оператор возврата, а не if. ;-)   -  person Dave Jarvis    schedule 16.10.2010
comment
распечатать результат отдельных фраз if (например, this.x == other.x) перед оператором if. Посмотрите, какие из них терпят неудачу.   -  person Tony Ennis    schedule 16.10.2010
comment
Являются ли какие-либо из сравниваемых переменных типами объектов, а не примитивными типами?   -  person robert_x44    schedule 16.10.2010
comment
Теперь подождите, то, что я делаю, сравнивает адреса памяти или фактические значения?   -  person Snowman    schedule 16.10.2010
comment
Он будет сравнивать значения. Вы запустили свой код, чтобы увидеть, работает ли он?   -  person Anthony Forloney    schedule 16.10.2010
comment
@frime - это зависит от того, являются ли x, y, направление и цвет типами значений или ссылочными типами.   -  person Oded    schedule 16.10.2010
comment
Типы значений будут сравниваться по значению, ссылочные типы (объекты) будут сравниваться по ссылке (адресу).   -  person Oded    schedule 16.10.2010


Ответы (4)


Поскольку color выглядит как Color, это класс и, следовательно, ссылочный тип, что означает, что вам нужно использовать equals() для сравнения цветов.

if (/* ... && */ this.color.equals(other.color)) {

Как отмечено в комментариях, использование == для сравнения ссылочных типов на самом деле сравнивает адреса памяти в Java. Он вернет true только в том случае, если они оба ссылаются на один и тот же объект в памяти.


akf указывает, что вам нужно использовать базовый класс Object для вашего параметра, в противном случае вы не переопределяете Object.equals(), а фактически перегружаете его, т.е. предоставляете другой способ вызова одноименного метода. Если вы случайно передадите объект совершенно другого класса, может произойти неожиданное поведение (хотя опять же, если они относятся к разным классам, он все равно вернет false правильно).

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Ghost))
        return false;

    // Cast Object to Ghost so the comparison below will work
    Ghost other = (Ghost) obj;

    return this.x == other.x
        && this.y == other.y
        && this.direction == other.direction
        && this.color.equals(other.color);
}
person BoltClock    schedule 16.10.2010
comment
Ааа ок понял. У меня уже был создан метод equals, поэтому я просто использовал его в поле цвета, и теперь он работает :) Спасибо. - person Snowman; 16.10.2010

В принципе, это выглядит нормально.

Однако обратите внимание, что вы сравниваете, используя ==. Для примитивов это не проблема, но для объектов будет проверяться один и тот же экземпляр, а не одно и то же значение. Это может быть или не быть тем, что вы хотите. Если вы сравниваете, например. java.lang.Strings, вместо этого вы хотите использовать equals (и проверить наличие null).

person sleske    schedule 16.10.2010

Если вы сравниваете объектные переменные вместо примитивных типов, вместо этого вы должны использовать сравнение this.color.equals(other.color).

В вашем случае это также зависит от того, как вы создали объекты Color. если вы использовали статические экземпляры (например, Color.BLUE), то на самом деле это не должно иметь значения. Если вы создали объект Color из значений RGB, это определенно имеет значение. В любом случае лучше привыкнуть к использованию .equals() для объектных переменных.

person robert_x44    schedule 16.10.2010

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

public boolean equals(Ghost other){

Вы должны иметь:

public boolean equals(Object other){

а затем внутренне проверьте, является ли параметр other параметром instanceof Ghost и приведен ли он по мере необходимости.

person akf    schedule 16.10.2010
comment
+1 Хороший улов там. Должен ли я исправить свой ответ, поскольку в его нынешнем виде вторая часть моего ответа неверна? - person BoltClock; 16.10.2010
comment
да, добавьте его для более полного ответа. - person akf; 16.10.2010