比较具有大量属性的 class 的两个实例

Comparing two instances of class having big number of attributes

我有一个 class 有超过 30 个属性。

我想覆盖 equals 方法以便比较我的 class.

的两个实例

但是我想避免像这样重写我的方法中的所有 30 个属性

@Override
public boolean equals(java.lang.Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    Address address = (Address) o;
    return Objects.equals(this.attr1, address.attr1) &&
            Objects.equals(this.attr2, address.attr2) &&
            Objects.equals(this.attr3, address.attr3) &&
            ......
            Objects.equals(this.attr30, address.attr30);

}

你有更简单妥当的方法吗?

你在 apache commons 库中有这个方法,它使用反射来比较它们

org.apache.commons.lang.builder.EqualsBuilder.reflectionEquals(Object, Object)

示例

import org.apache.commons.lang.builder.EqualsBuilder;

public class MyObject {

   ...
   @Override
   public boolean equals(Object obj) {
      return EqualsBuilder.reflectionEquals(this, obj);
  }
}

您可以使用 lombok 项目在构建时自动生成 hashCode 和 equals 方法。

您可以像这样在 java.lang.reflect 包中使用 Field class:

@Override
public boolean equals(Object o) {
    //instanceof check, null check, etc

    Field[] fields = Address.class.getDeclaredFields();

    for (Field field : fields) {
        try {
            field.setAccessible(true);

            if (!field.get(this).equals(field.get((Address) o))) {
                return false;
            } //end if
        } catch (IllegalAccessException e) {
            //handle exception
        } //end try catch
    } //end for

    return true;
} //equals

好吧,这基本上是必要的样板代码类型。幸运的是,有很多开发人员和您一样讨厌编写这样的代码。出于这样的原因,龙目岛项目成立了。

see this link.

例如,请参阅从我上面链接的页面中提取的以下两个代码片段:

龙目岛

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(exclude={"id", "shape"})
public class EqualsAndHashCodeExample {
  private transient int transientVar = 10;
  private String name;
  private double score;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;

  public String getName() {
    return this.name;
  }

  @EqualsAndHashCode(callSuper=true)
  public static class Square extends Shape {
    private final int width, height;

    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }
}

原版 Java

import java.util.Arrays;

public class EqualsAndHashCodeExample {
  private transient int transientVar = 10;
  private String name;
  private double score;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;

  public String getName() {
    return this.name;
  }

  @Override public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof EqualsAndHashCodeExample)) return false;
    EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
    if (!other.canEqual((Object)this)) return false;
    if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
    if (Double.compare(this.score, other.score) != 0) return false;
    if (!Arrays.deepEquals(this.tags, other.tags)) return false;
    return true;
  }

  @Override public int hashCode() {
    final int PRIME = 59;
    int result = 1;
    final long temp1 = Double.doubleToLongBits(this.score);
    result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
    result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
    result = (result*PRIME) + Arrays.deepHashCode(this.tags);
    return result;
  }

  protected boolean canEqual(Object other) {
    return other instanceof EqualsAndHashCodeExample;
  }

  public static class Square extends Shape {
    private final int width, height;

    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }

    @Override public boolean equals(Object o) {
      if (o == this) return true;
      if (!(o instanceof Square)) return false;
      Square other = (Square) o;
      if (!other.canEqual((Object)this)) return false;
      if (!super.equals(o)) return false;
      if (this.width != other.width) return false;
      if (this.height != other.height) return false;
      return true;
    }

    @Override public int hashCode() {
      final int PRIME = 59;
      int result = 1;
      result = (result*PRIME) + super.hashCode();
      result = (result*PRIME) + this.width;
      result = (result*PRIME) + this.height;
      return result;
    }

    protected boolean canEqual(Object other) {
      return other instanceof Square;
    }
  }
}

如果您喜欢这种方法,我建议您完整查看 Project Lombok。它确实有助于清理您的代码!

!!!当心!!! 为了能够实际使用 Lombok 生成的方法,您需要将 Lombok 插件安装到您的 IDE!否则,您的 IDE 将不知道自动生成的方法。

您可以使用 Unitils http://www.unitils.org/cookbook.html

import static org.unitils.reflectionassert.ReflectionAssert.*;
// Exact field-by-field comparison
assertReflectionEquals(new Person("John", "Doe", new Address("New street", 5, "Brussels")), 
                             new Person("John", "Doe", new Address("New street", 5, "Brussels"));