如何在不增加圈复杂度的情况下覆盖等于?

时间:2017-01-26 12:46:36

标签: java override equals

我最近在我最近的Java项目的域对象中覆盖了一些equals方法。当我们使用Sonar计算我们的代码指标时,我立即看到这些类的圈复杂度增加到超过阈值。

我想知道是否有一种聪明的方式,模式或选项可以保持这个指标较低,尽管有一些更复杂的equals方法。

编辑:这是我的一个例子,我没有具体说明,只是为了让我们知道我们在谈论什么。

@Override
public boolean equals(Object o) {
  if (o instanceof MyKey) {
  MyKey other = (MyKey) o;
  if (this.foo.longValue() == other.getFoo().longValue() &&
    this.bar.equalsIgnoreCase(other.getBar()) &&
    this.foobar.shortValue() == other.getFoobar().longValue()){
    return true;
    }
  }
  return false;
}

@Override
public int hashCode() {
  int hash = 3;
  hash = 53 * hash + foo.hashCode();
  hash = 53 * hash + bar.hashCode();
  hash = 53 * hash + foobar.hashCode();
  return hash;
}

2 个答案:

答案 0 :(得分:5)

您可以使用Apache的EqualsBuilder:

public boolean equals(Object obj) {
  if (obj == null) { return false; }
  if (obj == this) { return true; }
  if (obj.getClass() != getClass()) {
    return false;
  }
  MyClass rhs = (MyClass) obj;
  return new EqualsBuilder()
             .appendSuper(super.equals(obj))
             .append(field1, rhs.field1)
             .append(field2, rhs.field2)
             .append(field3, rhs.field3)
             .isEquals();
}

答案 1 :(得分:1)

您没有,但是您应该始终检查nullfoo可能是null,结果是NullPointerException

this.foo.longValue() == other.foo.longValue()

幸运的是,Objects实用程序类可以自动检查null,从而避免了很多问题。

@Override
public boolean equals(Object object) {
    if (object == null)
        return false;

    if (!(object instanceof MyObject))
        return false;

    MyObject other = (MyObject) object;

    //@formatter:off
    return Objects.equals(getX(), other.getX()) &&
           Objects.equals(getY(), other.getY()) &&
           Objects.equals(getZ(), other.getZ()));
    //@formatter:on
}

@Override
public int hashCode() {
    return Objects.hashCode(getX(), getY(), getZ());
}

如果要检查的字段很多,则可以选择在equals方法的开头添加该字段。

if (object == this)
    return true;

理论上,在某些情况下可以节省一些计算。

在我看来,唯一真正有用的是好的缩进。我总是将这些行放在一对//@formatter:off//@formatter:on之间。无论如何,这都是样板代码:非常容易编写,非常容易出错。

不过,对于您而言,您正在使用equalsIgnoreCase检查是否相等。可惜Objects没有这样的方法。您可以轻松构建自己的文件。

public final class Strings {
    public static boolean equalsIgnoreCase(String a, String b) {
        return a == null ? b == null : a.equalsIgnoreCase(b);
    }

    private Strings() {
    }
}

并像这样使用它

return Objects.equals           (getX(), other.getX()) &&
       Strings.equalsIgnoreCase (getY(), other.getY()) &&
       Objects.equals           (getZ(), other.getZ()));