深入equals方法
????? equals方法的重要性毋须多言,只要你想比较的两个对象不原是同一对象,你就应该实现equals方法,让对象用你认为相等的条件来进行比较.
????? 下面的内容只是API的规范,没有什么太高深的意义,但我之所以最先把它列在这儿,是因为这些规范在事实中并不是真正能保证得到实现.
1.对于任何引用类型, o.equals(o) == true成立.
2.如果 o.equals(o1) == true 成立,那么o1.equals(o)==true也一定要成立.
3.如果 o.equals(o1) == true 成立且? o.equals(o2) == true 成立,那么? o1.equals(o2) == true 也成立.
4.如果第一次调用o.equals(o1) == true成立再o和o1没有改变的情况下以后的任何次调用都成立.
5.o.equals(null) == true 任何时间都不成立.
????? 以上几条规则并不是最完整的表述,详细的请参见API文档.
????? 对于Object类,它提供了一个最最严密的实现,那就是只有是同一对象是,equals方法才返回true,也就是人们常说的引用比较而不是值比较.这个实现严密得已经没有什么实际的意义,所以在具体子类(相对于Object来说)中,如果我们要进行对象的值比较,就必须实现自己的equals方法.
????? 先来看一下以下这段程序:
?????
??? }??? public boolean equals(Object o) {
??????? if(o == this)
??????????? return true;
??????? if(!(o instanceof PhoneNumber))
??????????? return false;
??????? PhoneNumber pn = (PhoneNumber)o;
??????? return pn.extension == extension && pn.exchange == exchange && pn.areaCode == areaCode;
??? }
}注意这个类是final的,所以这个equals实现没有什么问题。
我们来测试一下:
??? public static void main(String[] args) {
??????? Map hm = new HashMap();
??????? PhoneNumber pn = new PhoneNumber(123, 38942, 230);
??????? hm.put(pn, "I love you");
??????? PhoneNumber pn1 = new PhoneNumber(123, 38942, 230);
??????? System.out.println(pn);
??????? System.out.println("pn.equals(pn1) is " + pn.equals(pn1));
??????? System.out.println(hm.get(pn1));
??????? System.out.println(hm.get(pn));
??? }
既然pn.equals(pn1),那么我put(pn,"I love you");后,get(pn1)这什么是null呢?
答案是因为它们的hashCode不一样,而hashMap就是以hashCode为主键的。所以规范要求,如果两个对象进行equals比较时如果返回true,那么它们的hashcode要求返回相等的值。
?