一, equals
之前只知道String中的equals 方法和 == 的区别,后来发现超类Object 中有equals() 方法,String中只是对equals 方法的重写。
Java 中每个类都使用Object 作为超类,因此没有重写的话就是使用默认的equals()方法:
public boolean equals(Object obj) {
return (this == obj);
}
即 等价于“==”方法。比较的是连个引用是否指向内存中同一个对象。
如果只是相比较两个对象在逻辑上是否相等,则需要重写equals 方法。String,Math,Integer 等封装类在使用equals 方法时,已经重写了Object 类的equals() 方法。
二,equals 重写注意的问题
在Java规范中,它对equals()方法的使用必须要遵循如下几个规则:
equals 方法在非空对象引用上实现相等关系:
1、自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
2、对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
3、传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
4、一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
5、 对于任何非空引用值 x,x.equals(null) 都应返回 false。
上面这几点可以看到重写equals() 方法需要注意的地方有很多。
public class EqualsTest {
public static void main(String[] args) {
People p1 = new People("a",12);
People p2 = new People("a",12);
People p3 = new People("b",13);
if(p1.equals(p2)){
System.out.println("p1 等于 p2;");
}else
System.out.println("p1 不等于 p2;");
}
}
class People {
private String name;
private int age;
public People(String name,int age){
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
没有重写equals() 方法,比较的还是引用指向的是否是同一对象,则输出:p1 不等于 p2;
重写了equals() 方法之后:
@Override
public boolean equals(Object obj){
if(obj!=null&&obj.getClass()==this.getClass()){
People p = (People) obj;
if((p.getName().equals(this.getName()))&&(p.getAge()==this.getAge()))
return true;
}
return false;
}
输出:p1 等于 p2
注意:这里进行类型判断的时候使用的getClass()
而不是instanceof
.
因为如果该类被继承,当使用父类的equals 方法比较是否与子类相等时,可能会出现错误。
class Student extends People{
private int id;
public Student(String name,int age,int id){
super(name, age);
this.id=id;
}
@Override
public boolean equals(Object obj){
....
}
}
比较子类额父类是否相等时:
Student s = new Student("a",12,11)
if(p1.equals(s)){
System.out.println("p1 等于 s;");
}else
System.out.println("p1 不等于s;");
}
如果equals方法中用 instanceof 判断时,则会错误的输出 p1 等于 s .而使用getClassName 则不会出现这种错误。
三,重写 hashcode
hashcode 方法返回该对象的哈希码值,hashcode可以用来提高Map 中搜索效率。
Map 搜索一个对象时先通过hashCode() 找到相应的位置,然后根据equals 方法判断这个位置上的对象与被搜索的对象是不是同一个。
所以,Java对于eqauls方法和hashCode方法是这样规定的:
1、当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true;
2、当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false
因此在重写equals方法时有必要重写hashcode。否则在存储散列集合时,将会存储两个值一样hash码不同的对象。
参考:
http://www.cnblogs.com/skywang12345/p/3324958.html#top
http://www.cnblogs.com/chenssy/p/3416195.html
http://book.51cto.com/art/201202/317531.htm
http://blog.csdn.net/naughty610/article/details/7027583