Java字符串之`equals`与`==`
2017-09-26 本文已影响11人
谢随安
参考:知乎专栏《Java那些事儿》
其实前段时间自己写代码的时候就注意到这个问题了,不过那时候并没有写下来的想法,现在复习Java基础又看到相关的文章,就当练习Markdown把这个问题写下来好了。
执行如下代码:
public class StringCmp {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
System.out.println("Using `==`:");
System.out.println("str1 == str2:" + (str1 == str2));
System.out.println("str3 == str4:" + (str3 == str4));
System.out.println("Using `equals`:");
System.out.println("str1.equals(str2):" + str1.equals(str2));
System.out.println("str3.equals(str4):" + str3.equals(str4));
}
}
执行结果如下:
Using `==`:
str1 == str2:true
str3 == str4:false
Using `equals`:
str1.equals(str2):true
str3.equals(str4):true
equals
的结果是我们预期想要的,但==
却不是,这是为何呢?
然而这次出现不同结果的原因却与Integer那篇文章的原因不同----这次并非是编译器的锅,编译器并没有在编译的时候偷偷修改代码。
原因在于:
- 当代码执行到
String str1 = "abc"
,就在堆空间的常量池中查询"abc"这个对象,发现常量池中没有,则在常量池里创建并初始化该对象,并将引用指向它。 - 当代码执行到
String str2 = "abc"
,同样在堆空间的常量池中查询"abc"这个对象,发现常量池中存在该对象,于是将引用同样指向"abc"。
而由于str1,str2 两个对象指向同一个引用,因此str1 == str2输出为true。
而str3 == str4
的结果为false的原因在于:
- 当代码执行到
String str3 = new String("abc");
与String str4 = new String("abc");
时,new
关键字告诉JVM要在堆空间里使用一段新的空间用来创建一个新的对象。所以JVM为
str3
和str4
都分别在堆空间中创建了一个属于它们的空间。
因此执行str3.==(str4)
时,由于str3
和str4
不是指向同一个引用,因此结果为false。
结论:
==
的意义是内存地址的比较,而非值本身,比较值一定要使用equals
去比较,Java并不支持重载操作符