Реализация шаблона проектирования метода equals()

Есть ли шаблон проектирования (или идиома), который помогает реализовать equals() метод в Java?

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

UPDATE

Я выбрал метод: generate equals() method in Eclipse но... я нашел хороший способ (в AbstractList) сделать этот сгенерированный код лучше:

if (!(attributes ==null ? other.attributes==null : attributes.equals(other.attributes))) 
    return false; 

вместо сгенерированного:

if (attributes == null) {
        if (other.attributes != null)
        return false;
    } else if (!attributes.equals(other.attributes))
        return false;

7 ответов

Решение

Обычно для реализации метода equals() я создаю их из Eclipse, так как Eclipse может очень хорошо генерировать методы hashCode, toString и equals().

Я всегда использую следующий код:

if (null == obj) return false;
if (this == obj) return true;
if (!(object instanceof MyClass)) return false;
MyClass that = (MyClass) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(this.businessKey, that.businessKey);
return eb.isEquals();

...

Я никогда не использую технические ключи, такие как последовательности или ПК, всегда бизнес-поля. Поэтому я не верю, что это может быть сделано общим, но должно быть сделано специфичным для любого данного класса.

Посмотрите, что должна сказать спецификация языка Java.

equals Метод просто определяет понятие равенства объектов

Кроме того, при разработке этого метода не используется шаблон проектирования. Правда в том, что equals Метод уже разработан дизайнерами языка Java, и вы можете использовать только дизайн. Если вы не уверены в том, как написать собственный метод equals, попробуйте воспользоваться помощью IDE, например eclipse, которая сделает эту работу за вас.

Может быть, это помогает: реализация равных. Особенно следует помнить о близких отношениях между hashcode() и equals(). Кроме этого, я полагаю, что конкретная реализация equals () действительно зависит от вашего класса, то есть когда вы рассматриваете два объекта как равные.

Вы сами решаете, когда два объекта являются "одинаковыми" в определенном смысле... Должны ли они быть равными, если они содержат одни и те же данные (совершенно допустимый сценарий использования), или, более строго, когда они являются одним и тем же физическим объектом в память (также допустимая) или точно такая же строка в БД при сравнении в кластерной среде?

Просто не забудьте переопределить .hashCode() или вы в мире боли:-)

(Кроме того, хорошие предложения статей от @Andreas и @flash.)

Ура,

Этот шаблон зависит от новой функции сопоставления шаблонов, выпущенной для предварительной версии в Java 14 (2020/март/17), а затем полностью выпущенной в Java 16 (2021/март/16).


Мне действительно не нравится видеть явное использованиеtrueиfalse, особенно когда они напрямую выпадают из оцениваемой логики.

Итак, мне совсем не нравится шаблон кода по умолчанию, созданный моей IDE (IntelliJ) при переопределении и реализацииequals()в моих классах.

Это выглядит так:

      public boolean equals(Object o) {
  if (this == o) {
    return true;
  }
  if (o == null || getClass() != o.getClass()) {
    return false;
  }
  EqualsExampleClass that = (EqualsExampleClass) o;
  return Objects.equals(stringy, that.stringy)
      && (inty == that.inty)
      && Objects.equals(bigIntegery, that.bigIntegery)
      && (booleany == that.booleany);
}

Воодушевлен Oracle JEP 394 дляinstanceofсопоставление с образцом, я изменил приведенный выше код, чтобы он выглядел следующим образом:

      @Override
public boolean equals(Object o) {
  return (this == o) ||
      ((o instanceof EqualsExampleClass that)
          && (this.getClass() == that.getClass())
          && Objects.equals(this.stringy, that.stringy)
          && (this.inty == that.inty)
          && Objects.equals(this.bigInt, that.bigInt)
          && (this.booleany == that.booleany));
}

Подробности выполнения построчно:

  1. (this == o)- проверяет буквально один и тот же экземпляр
  2. (o instanceof EqualsExampleClass that)- проверьте, не является ли , экземпляром этого класса (или его потомком), и если да, присвойтеoк переменной суженного типаthat
  3. (this.getClass() == that.getClass())- требует сравнения с точно таким же классом (а не потомком)
  4. Objects.equals(this.stringy, that.stringy)- с использованиемObjects.equals()на ссылки (не примитивы), чтобы убедиться, что какая-либо сторона возвращаетnull, сравнение производится без бросанияNullPointerException

Я обнаружил, что этот шаблон реализации кода значительно проще для функционального чтения, анализа, анализа и отладки во время рефакторинга.

Не уверен насчет ваших ожиданий. equals() предназначен для определения ваших критериев сравнения двух разных объектов вашего класса на равенство.

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

Другие вопросы по тегам