之前看到IdentityHashMap和HashMap的具体区别时发现,IdentityHashMap使用==判断两个key是否相等,而HashMap使用的是equals方法比较key值。
那么 equals方法和==到底有什么区别呢?
1、“==”
我们来看一个简单的例子。
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=3;
int m=3;
System.out.println(n==m);
String str = new String("hello");
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1==str2);
str1 = str;
str2 = str;
System.out.println(str1==str2);
}
输出结果为 true false true
n==m结果为true,这个很容易理解,变量n和变量m存储的值都为3,肯定是相等的。而为什么str1和str2两次比较的结果不同?要理解这个其实只需要理解基本数据类型变量和非基本数据类型变量的区别。
在Java中游8种基本数据类型:
浮点型:float(4 byte), double(8 byte)
整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
字符型: char(2 byte)
布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值”true”和”false”)
对于基本数据类型,他们的数据直接存储在栈中,而==直接是判断他们存储在栈中的诗句是否相等。
int x=1;
int y=1;
System.out.println(x==y);
输出结果为true;
而对于非基本数据类型,比如数组,数组在栈中存储的是一个地址,而他的真实值存储在堆中。
有关更多内存分配的问题可以参考http://blog.csdn.net/qq_34149805/article/details/53365177
这时候再调用==方法比较的就是他们栈中存储的的地址,两个new出来的数组他们的地址肯定是不同的,所以
int[] arr1 = new int[]{1,2,3};
int[] arr2 = new int[]{1,2,3};
System.out.println(arr1 == arr2);
输出结果为false
看我们上面的例子,在用==对str1和str2进行第一次比较时,得到的结果是false。因此它们分别指向的是不同的对象,也就是说它们实际存储的内存地址不同。
而在第二次比较时,都让str1和str2指向了str指向的对象,那么得到的结果毫无疑问是true。
二、equals
看完上面的==会给人一个假象,equals方法一定是比较的存储在堆中的数据了!
其实并不然,我们来看Object提供的equals方法:
public boolean equals(Object obj) {
return (this == obj);
}
它仍然使用 == 来比较两个对象。
可见,如果另一个类不对equals方法进行重写,它的equals方法和 == 是没有区别的!比如数组。
我们再来看String的equals方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
可以看出,String类对equals方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。
其他的一些类诸如Double,Date,Integer,HashMap等,都对equals方法进行了重写用来比较指向的对象所存储的内容是否相等。
总结
对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址
对于equals方法,注意:equals方法不能作用于基本数据类型的变量
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
equals小问题
这里还要说一个equals的小问题
就是在使用equals时为什么要把常量写在前面
“abc”.equals(strData)
如果 strData=null;
那么 strData.equals(“abc”);就会抛出异常。
而 “abc”.equals(strData);则是fals