简单的一句话说明就是:
==比较Stack中的值(引用数据类型stack中存放的是对象的堆内存地址)。
equals() 通常被覆写为比较对象的值
那么==和equals()之间到底有什么具体的区别呢?
如果单从Object类或继承于Object没有做出任何覆写操作的类来看,==和equals()之间没有任何区别,equals方法由Object类提供,在Object中对equals的实现是这样的:
public boolean equals(Object o){
return this == o;
}
但事实是API中的大部分类为我们重写了equals方法,例如String中,equals方法就被覆写为了对值的比较,String中的equals是这样操作的:
判断传入方法的字符串与当前字符串长度是否一致,如果不一致则没有必要再进行比较了,直接返回false
如果长度一致则把两个支付串转换成char数组,通过循环对两个数组中的同位元素进行比较,其中有任意一对同位元素不一致则中断循环,返回false
如果循环完成任然没有跳出循环,则在循环自然中断后返回true
由此可见,在String中的equals实际是在对字符串的每一个值进行比较
但有时候==确让我们在比较值的错觉,如下列情况:
String a="Test";
String b="Test";
if(a= =b) ===> true
结果确实是我们想要得到的true,似乎比较成功了,但是!
这是因为当你创建任何字符串文字时,JVM首先在字符串池中搜索该文字,并且如果找到匹配项,那么同样的引用将被赋予新的String。因此,我们得到了
(a = = b)===> true
简而言之就是a和b指向了相同的堆内存区
String Pool
b -----------------> "test" <-----------------a
但是,==在以下情况下失败。
String a="test";
String b=new String("test");
if (a==b) ===> false
在这种情况下,new String("test")对于新的String将在堆内存区中创建新的引用赋予给b,此时b所指向的内存地址与a指向不同
if(a == b)===> false。
String Pool
"test" <-------------------- a
Heap
"test" <-------------------- b
那在Integer等包装类型又会如何呢:
我们不妨来看看下面这个实验
Integer i_1 = 1;
Integer i_2 = 1;
Integer i_3 = new Integer(1);
System.out.println(i_1.equals(i_2)); //true
System.out.println(i_1.equals(i_3)); //true
System.out.println(i_1 == i_2); //true
System.out.println(i_1 == i_3); //false
好了,看上去一切真相大白,这个结果和我们期望的一模一样,真是这样吗?我们把i_1和i_2的值进行一个修改看看
Integer i_1 = 128;
Integer i_2 = 128;
System.out.println(i_1 == i_2);
这个结果出人意料的返回了false,这是什么原因?看看Integer的equals方法实现过程
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
这个方法告诉我们,Integer其实还是在用==做对象的比较,其中的value是一个int类型,在Integer中定义value是这样的
private final int value;
这个方法毫无争议,它和String中的equals有相同的思想。
我们在看看Integer i_1 = 1这段代码,其实Integer i_1 = 1的这种操作形式是调用Integer的valueOf方法,而valueOf方法在Integer中的声明如下:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
不难发现,在某个范围内Intger直接从IntegerCache中取值,超出了这个范围则执行new Intger,而IntegerCache的范围正好是-128~127,因此,当Integer i_1和i_2直接赋值这个范围时==返回为true,超出范围自然返回为false
所以当你不知道到底应该使用哪个方法时,使用.equals()总是更好的。
文章原创。
若转载,请注明出处:“来自蜗牛学院cto李懿老师”。
若没有按照以上注明出处,一经发现必追究。
作者:蜗牛学院CTO李懿老师
蜗牛学院,一家有态度的IT培训机构。
网友评论