我们假设我有课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();
}
答案 0 :(得分:7)
是否应该这样做取决于你班级的语义。也就是说,意味着什么来说你的班级的两个对象是等价的?最重要的区别在于具有值语义的对象和具有实体语义的对象之间。实体对象即使具有相同的属性(颜色,长度等)也不相等。在许多情况下,包括从具有主键的数据库表中读取对象时,实体对象将具有唯一的ID字段。在这种情况下仅比较ID字段是正确的事情。
答案 1 :(得分:0)
没关系。只要没有两个不同的用户可以拥有相同的ID,您的equals
功能就足够了。如果一个用户可以使用不同的ID(无论出于何种原因)两次表示,并且您确实希望将它们视为相等,则可能会出现问题。
答案 2 :(得分:0)
你的equals()方法看起来不像它是由IDE生成的,因为它没有检查@Eric所声明的'id'null值。
这就是我的equals()/ hashCode()方法看起来像使用相同的id prop
@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'道具的唯一性的观点,这取决于你的偏好以及你想如何使用你等于方法(业务要求),即如果两个用户的名字相同,那么当比较两个时,它们被认为是相同的用户对象稍后..
答案 3 :(得分:0)
只要您不必将尚未保留的实体与数据库进行比较,就可以使用equals
方法的id。如果您想比较尚未保存的实体,则必须比较它们的属性。
答案 4 :(得分:0)
我同意这是id。 但是在获取应该更新数据库的数据时我遇到了麻烦。 使用User的这个例子,其中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);
你是否同意这是一种方法。 ??????