判断对象的等价性
2018-06-11 16:52:47
对象等价性的判断
- 如下一个简单的小栗子
1 /** 2 * 3 * @author Accper 4 * 5 */ 6 public class Equivalence { 7 public static void main(String[] args) { 8 Integer n1 = new Integer(50); 9 Integer n2 = new Integer(50); 10 System.out.println(n1 == n2); 11 System.out.println(n1 != n2); 12 } 13 }
- 运行的结果为:false true。很多人第一反应肯定是一脸懵逼,别看程序短其实要追究起来,还是可以挖的很深,首先明确一点的是,"=="和"!="判断的是对象的引用;其次,两次new Integer(50),在堆储存空间中分配了两个内存空间,每个内存空间都有一个地址,对象的引用就是指向这个地址,所以两次new的对象的地址是不同的。
- 如果上面的程序懂的话,但是有的人会问,我就是想比较它们的值,你能把我咋地。好吧,我们接着进行,快看下面的栗子
1 /** 2 * 3 * @author Accper 4 * 5 */ 6 public class EqualsMethod { 7 public static void main(String[] args) { 8 Integer n1 = new Integer(50); 9 Integer n2 = new Integer(50); 10 System.out.println(n1.equals(n2)); 11 } 12 }
- 没错真如与其所想那样子,运行的结果为:true。注意一点的是,此方法不适用于"基本类型",基本类型是可以直接使用==和!=的。
- 为了验证上面所学,我们再来一个栗子,看下面代码
1 /** 2 * 3 * @author Accper 4 * 5 */ 6 class Value { 7 int i; 8 } 9 10 public class EqualsMethod2 { 11 public static void main(String[] args) { 12 Value v1 = new Value(); 13 Value v2 = new Value(); 14 v1.i = v2.i = 99; 15 System.out.println(v1.equals(v2)); 16 } 17 }
- 没错,what is the fuck!运行结果是false。想知道为什么请看下面如何分析。
分析
- 首先,请看Integer类中equals的源码,现在知道为什么上面的"n1.equals(n2)"结果为true了,因为Integer中的equals的确实是对其中的值进行比较的,不是引用。
1 /** 2 * Compares this object to the specified object. The result is 3 * {@code true} if and only if the argument is not 4 * {@code null} and is an {@code Integer} object that 5 * contains the same {@code int} value as this object. 6 * 7 * @param obj the object to compare with. 8 * @return {@code true} if the objects are the same; 9 * {@code false} otherwise. 10 */ 11 public boolean equals(Object obj) { 12 if (obj instanceof Integer) { 13 return value == ((Integer)obj).intValue(); 14 } 15 return false; 16 }
- 那有的人会问,那为什么"v1.equals(v2)"的结果为false呢?我们知道所有类的祖宗都是Object类,而Value类中没有对equals方法进行重写,所以我们来看Object中equals方法的源码。因为Value类中直接使用的是Object类中的equals方法,所以还是判断的是对象的引用,不是其中的值。
1 /** 2 * Note that it is generally necessary to override the {@code hashCode} 3 * method whenever this method is overridden, so as to maintain the 4 * general contract for the {@code hashCode} method, which states 5 * that equal objects must have equal hash codes. 6 * 7 * @param obj the reference object with which to compare. 8 * @return {@code true} if this object is the same as the obj 9 * argument; {@code false} otherwise. 10 * @see #hashCode() 11 * @see java.util.HashMap 12 */ 13 public boolean equals(Object obj) { 14 return (this == obj); 15 }
总结
- 还是源码大法好,没事的时候还是多研究研究源码,方知为什么。