java 中的“==”跟equals()

java 中的“==”和equals()
    在Java中“==”和equals()都有比较的意思,只是比较的内容不同,以前自己错认为“==”比较的是句柄(引用),equals()比较的是内容,但是通过下面这个程序可以发现问题:

class Value {
int i;
}
public class EqualsMethod {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = 100;
v2.i = 100;
System.out.println(v1 == v2);
System.out.println(v1.equals(v2));
  }
}

输出结果:
false
false

    结果并不是想象的false和true,这是为什么呢?通过查资料之后找到了原因:对于String 、Integer、Double等这些封装类来说,这些类重写了Object中的equals()方法,让它不再比较句柄(引用),而是比较对象中实际包含的值,即比较的是内容。而Object的equals()方法比较的是地址值,上面程序自定义的类Value继承了Object的equals()方法,如果不重写,那么比较的就是句柄(引用)。
  
public boolean equals(Object obj) {
return (this == obj);
}

   上面一段程序是Object的equals()方法定义,由此可以看出,在object类中“==”和equals()方法的作用是相同的,他们比较的都是句柄(引用)。

    如果想比较上面程序中v1和v2的内容,可以重写equals()方法和hashCode()方法,修改后的程序如下:

class Value {
int i;
public int hashCode()
{
return i*hashCode();
}
public boolean equals(Object o)
{
   Value v=(Value)o;
   return i==v.i;
}

}
public class EqualsMethod {
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = 100;
v2.i = 100;
System.out.println(v1 == v2);
System.out.println(v1.equals(v2));
  }
}

输出结果:
false
true
   经过重写后,equals()方法比较的是对象中包含的值,因为对象v1和v2都只有一个相同的属性i,且都等于100,因此v1.equals(v2)输出true。

   在这里说明一下,为什么在重写equals()方法的时候还要重写hashCode()方法。在java的集合中,判断两个对象是否相等的规则步骤是:
1、判断两个对象的hashCode是否相等
2、如果不相等,认为两个对象也不相等
3、如果相等,则判断两个对象用equals运算是否相等
4、如果不相等,认为两个对象也不相等
5、如果相等,认为两个对象相等
   在理论上hashCode()方法不重写,运行结果也是false和true,但是这样就会降低存储效率,通常情况下,会将重写hashCode()方法看成是必须的。

   另外,还有一点需要记住,equals()相等的两个对象,hashCode()一定相等,
equals()不相等的两个对象,却并不能证明他们的hashCode()不相等。