我对java很新,我只是想了解@Override
和equals()
方法的hashcode()
。
我知道equals方法是正确的,它需要是:
a.equals(a)
a.equals(b)
然后 b.equals(a)
a.equals(b) && b.equals(c)
然后 a.equals(c)
! a.equals(null)
我正在努力确定上述哪些属性,并且在编写equals方法时,我并不满意。
我知道eclipse可以为我生成这些,但是因为我还没有完全理解这个概念,所以写出来有助于我学习。
我已经写出了我认为正确的方法,但是当我查看eclipse生成的版本时,我似乎错过了'某些方面。
示例:
public class People {
private Name first; //Invariants --> !Null, !=last
private Name last; // !Null, !=first
private int age; // !Null, ! <=0
...
}
我写的内容:
public boolean equals(Object obj){
if (obj == null){
return false;
}
if (!(obj instanceof People)){
return false;
}
People other = (People) obj;
if (this.age != other.age){
return false;
}
if (! this.first.equals(other.first)){
return false;
}
if (! this.last.equals(other.last)){
return false;
}
return true;
}
vs eclipse生成
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
People other = (People) obj;
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
if (age != other.age)
return false;
if (last == null) {
if (other.last != null)
return false;
} else if (!last.equals(other.last))
return false;
return true;
}
我失踪了:
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
并为每个变量:
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
我不确定getClass()
是什么,我的诽谤是不正确的?
答案 0 :(得分:8)
第一段代码:
if (this == obj)
return true;
如果您将对象引用与自身进行比较,这可以提高性能。示例:a.equals(a);
。
第二段代码:
if (getClass() != obj.getClass())
return false;
这比较了被比较的引用的类是否是this
的同一类。使用此方法与instanceof
之间的区别在于,在与子类进行比较时,它的限制性更强。例如:
public class Foo { }
public class Bar extends Foo { }
//...
Foo foo = new Bar();
System.out.println(foo instanceof Bar); //prints true
System.out.println(foo instanceof Foo); //prints true
Foo foo2 = new Foo();
System.out.println(foo.getClass() == foo2.getClass()); //prints false
你应该选择哪一个?没有好的或坏的方法,这取决于你想要的设计。
第三段代码:
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false; //For each variable.
这只是对类中每个对象引用字段的空检查。请注意,如果this.first
为null
,则执行this.first.equals(...)
会抛出NullPointerException
。
答案 1 :(得分:4)
我认为您的实施不正确,但有一些注意事项:
if (this == obj) return true;
是性能优化,它直接测试a
a
的参考相等和短路测试。
if (getClass() != obj.getClass()) return false;
与您的instanceof
调用相似,优化掉空检查。其他调用似乎是空检查。
答案 2 :(得分:3)
你不需要写
if (obj == null){
return false;
}
if (!(obj instanceof People)){
return false;
}
因为null
始终在false
次检查中提供instanceof
。所以这些行可以简化为
if (!(obj instanceof People)){
return false;
}
关于您的方法是否符合equals()
方法要求的主要问题,严格来说答案是否定的,或者至少它可能是狡猾的。这是因为可以按如下方式扩展类
public class SpecialPeople extends People {
// code omitted
@Override
public boolean equals(Object object) {
if (object == null || object.getClass() != getClass())
return false;
SpecialPeople other = (SpecialPeople) object;
return other.getAge() == getAge()
&& other.getFirst().equals(getFirst())
&& other.getLast().equals(getLast());
}
现在假设a
是People
的实例,而b
是SpecialPeople
的实例。假设a
和b
具有相同的名称和年龄。然后
a.equals(b) == true // instanceof check succeeds
b.equals(a) == false // getClass() check fails
因此equals()
不对称!因此,如果您在instanceof
中使用getClass()
而不是equals()
,则应该使用equals()
方法final
或类final
}。