自个儿对Java中==与equals比较的理解
首先我们先看三个实例结果:
实例1:
String s1 = new String("abc");
String s2 = new String("abc");
s1==s2——结果为false;
s1.equals(s2)——结果为true;
实例2:
Object obj1 = new Object();
Object obj2 = new Object();
obj1==obj2;
obj1.equals(obj2);
结果都为false;
示例3:
Object obj1 = new Object();
Object obj2 = obj1;
obj1==obj2;
obj1.equals(obj2);
结果都为true;
看到这三种结果,虽然大家都知道这个结果,初学者可能难免都会产生一种说不清道不明感觉,下面是个人对==和equals两种比较操作的理解,不对之处也请各们高手指正,以免我误道初学者。
首先我来解说示例1:
先让我们来看看String类equals方法的源码:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
如上代码所示,equals方法的第一步就是进行==比较,而我们知道,两个String类型的==比较结果是false,所以我们继续往下看代码,当==结果为false时,并且比较类型为String时,就会把两个String转化为char数组,通过比较char数组中的每个值来判断最终结果。
再先我来解说示例2:
还是让我们先看一段Object类equals方法的源码:
public boolean equals(Object obj) {
return (this == obj);
}
代码所示,当两个对象类型进行equals方法比较时,默认是进行==比较
这时大家可能会迷糊了,心里就会想:
Object obj1 = new Object();
Object obj2 = new Object();
如果obj1与obj2两个对象中的值完全一样,为什么他们的==和equals都会返回false呢?想不通,不急,不妨看看我说的对不对创建一个对象类型,如Object obj = new Object();在JVM中会开辟两块内存,一块为obj,在这我称之为变量内存(存储在栈中),一块为new Object();在这里我称之为对象内存(存储在堆中);而变量仅仅只是对象的一个引用而已。
在上面的示例中我们创建了obj1与obj2两个变量,分别在JVM中开辟了两块内存,同时并具有唯一内存地址,而当对象类型使用==进行比较时,恰恰就是比较的这两个对象的内存地址值(内存地址的其中一种表示形式就是hashcode值),所以对象类型的==结果为false。又因为Object的equals默认就是进行==比较,所以对象类型的equals返回结果也是false;
有了示例2的解说,相信大家对示例3的结果应该会比较清楚了,因为obj2=obj1,意味着new Object()不仅被obj1变量引用,同时还被obj2变量引用,所以,这两个变量指向同一块内存对象,所以他们的==和equals都为true。
简言之:
当比较的双方为基本数据类型时,==比较的是双方的值。
当比较的双方为对象数据类型时,==和equals都比较的是双方的变量所指向对象(值)的内存地址。
而通过示例1我们可以得出,引用类型的equals比较的是两个对象的内容是否相等。
所以我们在判断两个对象是否相等时,需要重写equals方法逐个判断对象中的内容是否相等。
所以使用使用对象clone出来的对象,双方==和equals也还是false,因为当我们clone对象时,仍然是返回一个new Object(),源Object与clone出的Object具有不相同的内存地址。