34

假设我有课User

public class User {
  private Long id;
  private String name;
  private Integer age;
  private BigDecimal account;
  // other fields, getters and setters
}

equals如下覆盖该方法是否合适?

@Override
public boolean equals(Object ob) {
   if (ob == null) {
       return false;
   }
   if (this == ob) {
       return true;
   }
   if (ob instanceof User) {
       User other = (User) ob;
       return this.id.equals(other.getId());
   }
   return false;
}

事实证明,对象的唯一性仅由其 ID 决定。但在我的应用程序中,id总是独一无二的。它在数据库中提供。我的equals实施是否足以说明这一点?或者这不是最佳实践?

当然,我知道在这种情况下,hashCode实现应该如下:

@Override
public int hashCode() {
   return id.intValue();
}
4

5 回答 5

9

你是否应该这样做取决于你的类的语义。也就是说,说你的类的两个对象是等价的是什么意思?

最重要的区别在于具有值语义的对象和具有实体语义的对象。实体对象不是等价的,即使它们具有等价的属性(颜色、长度等)。在许多情况下,包括从具有主键的数据库表中读取对象时,实体对象将具有唯一的 ID 字段。在这种情况下只比较 ID 字段是正确的做法。

于 2013-06-09T14:11:37.493 回答
2

equals只要您不必将尚未持久化的实体与数据库进行比较,就可以将id 用于方法。如果要比较尚未保存的实体,则必须比较它们的属性。

于 2013-06-09T14:42:02.157 回答
1

没关系。只要没有两个不同的用户可以拥有相同的 ID,您的equals功能就足够了。如果一个用户可以用不同的 ID 表示两次(无论出于何种原因)并且您确实希望将它们视为相等,则可能会出现问题。

于 2013-06-08T20:20:35.587 回答
1

您的 equals() 方法看起来不像是由 IDE 生成的,因为它不检查 @Eric 所述的“id”空值。

这就是我的 equals()/hashCode() 方法使用相同的 id 道具的样子

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    User11 other = (User11) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (!id.equals(other.id))
        return false;
    return true;
}

我们应该尽可能地使用自动生成样板代码,因为它不容易出错。

此外,关于您关于“id”道具唯一性的观点,这取决于您的偏好以及您希望如何使用您的 equals 方法(业务需求),即如果两个用户的名称相同,那么在稍后比较两个用户对象时是否将它们视为相同上..

于 2013-06-08T20:42:16.857 回答
0

我同意它在身份证上。但是我在获取应该更新数据库的数据时遇到了麻烦。在这个带有用户的例子中,equals 只查看了我创建的 ID。

interface DataEquals<T extends DataEquals> {
   public boolean isDataEquals(T other)
}


User implements DataEquals<User> {
   public boolean isDataEquals(User other) {
      boolean b1 = getName().equals(other.getName());
      boolean b2 = getAge().equals(other.getAge());
      boolean b3 = getAccount().equals(other.getAccount());
      return b1 && b2 && b3;
   }
}

有了这个,我们可以拥有这个。

public class ListChanges<T extends DataEquals<T>> {

  private List<T> added = new ArrayList<T>();
  private List<T> removed = new ArrayList<T>();
  private List<T> changed = new ArrayList<T>();
  private List<T> unchanged = new ArrayList<T>();

  public ListChanges() {
    super();
  }
  public List<T> getAdded() {
    return added;
  }
  public List<T> getChanged() {
    return changed;
  }
  public List<T> getRemoved() {
    return removed;
  }
  public List<T> getUnchanged() {
    return unchanged;
  }

  public boolean hasAnyChanges() {
    return added.size()>0 || removed.size()>0 || changed.size()>0;
  }

  public void parse(List<T> oldList,List<T> newList) {
    for (T oldObj : oldList) {
        int index =newList.indexOf(oldObj);
        if (index==-1) {
            removed.add(oldObj);
        } else {
            T newObj = newList.get(index);

            if (newObj.isDataEquals(oldObj)) {
                unchanged.add(oldObj);
            } else {
                changed.add(newObj);
            }
        }
    }
    for (T newObj : newList) {
        if (oldList.indexOf(newObj)==-1) {
            added.add(newObj);
        }
    }
 }
}

然后我们可以这样做

List<User> oldList = ....;
List<User> newList = ...;
ListChanges<User> listChanges = new ListChanges<User>();
listChanges.parseChanges(oldList,newList);

你同意这是一种方法吗????

于 2016-09-21T08:55:58.917 回答