转自:http://www.sunxin.org/forum/thread/19720.htmlhtml
先谈equals。 equals是Object类提供的方法之一,众所周知,每个java类都继承自Object类, 因此说每个对象都有equals这个方法。而咱们在用这个方法时却通常都重写这个方法,why?
Ok,先看一个Object类中equals()方法的源代码:java
public boolean equals(Object obj) { return (this == obj); }
从这个方法中能够看出,只有当一个实例等于它自己的时候,equals()才会返回true值。通俗地说,此时比较的是两个引用是否指向内存中的同一个对象,也能够称作是否实例相等。而咱们在使用equals()来比较两个指向值对象的引用的时候,每每但愿知道它们逻辑上是否相等,而不是它们是否指向同一个对象——这就是咱们一般重写这个方法的缘由。程序员
在程序员之家论坛中有这样一篇文章《全面理解Java中的String数据类型》(连接http://www.phome.asia/forum/thread/19667.html) ,在这篇文章中,String s1 = new String(“kvill”),String s2 = new String(“kvill”); s1.equals(s2)为ture,说明String类中已经重写了equals()方法,若是不重写equals()方法,那么s1.equals(s2)默认比较两个对象所指向的内存地址是否相同,返回值必然为false。性能
重写equals()方法看起来很是简单,可是有许多改写的方式会致使错误,而且后果很是严重。要想正确改写equals()方法,你必需要遵照它的通用约定。下面是约定的内容,来自java.lang.Object的规范,equals方法实现了等价关系,如下是要求遵循的5点,这5点都是当年数学的概念啊……,呵呵,且看:this
1. 自反性:对于任意的引用值x,x.equals(x)必定为true。 spa
2. 对称性:对于任意的引用值x 和 y,当x.equals(y)返回true时,y.equals(x)也必定返回true。 code
3. 传递性:对于任意的引用值x、y和z,若是x.equals(y)返回true,而且y.equals(z)也返回true,那么x.equals(z)也必定返回true。htm
4. 一致性:对于任意的引用值x 和 y,若是用于equals比较的对象信息没有被修改,屡次调用x.equals(y)要么一致地返回true,要么一致地返回false。对象
5. 非空性:对于任意的非空引用值x,x.equals(null)必定返回false。继承
了解了equals重写,咱们再看hashCode()这个方法,hashcode()这个方法也是从object类中继承过来的,在object类中定义以下:
public native int hashCode();
说明是一个本地方法,它的实现是根据本地机器相关的。再看它比较“官方”的详细说明:hashCode()返回该对象的哈希码值,该值一般是一个由该对象的内部地址转换而来的整数,它的实现主要是为了提升哈希表(例如java.util.Hashtable提供的哈希表)的性能。
你能够对它的这样“官方式”的定义漠视,但如下这一点你必须铭记:在每一个重写了equals方法的类中,你必须也要重写hashCode方法。若是不这样作的话,就会违反Object.hashCode的通用约定,从而致使该类没法与全部基于散列值(hash)的集合类结合在一块儿正常运行。
hashCode()的返回值和equals()的关系以下:
若是x.equals(y)返回“true”,那么x和y的hashCode()必须相等。
若是x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
说了这么多,他们之间的具体关系仍是看个例子好,如下是51px中吴老师的一个例子。
public class TestEquals { public static void main(String args[]) { Student s1 = new Student("张一", 6); Student s2 = new Student("张一", 6); if (s1.equals(s2)) { System.out.println("相同 s1的代码:" + s1.hashCode() + " s2的代码:" + s2.hashCode()); } else { System.out.println("不相同"); } } } class Student { private int age; private String name; public Student() { } public Student(String name, int age) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int hashCode() { return (this.name.hashCode() + this.age) * 31; } public boolean equals(Object obj) { boolean result = false; if (obj == null) { result = false; } if (this == obj) { result = true; } if (obj instanceof Student) { Student stu = (Student) obj; if (stu.getName().equals(this.name) && stu.getAge() == (this.age)) { result = true; } } else { result = false; } return result; } }