Java 中的equals

来源:互联网 发布:java io 装饰器模式 编辑:程序博客网 时间:2024/04/19 23:13

一, 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

0 0