今天在看JVM的时候突然想到这样一个问题,即
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2);//答案是false
问题有两个:
- String s2 = “abc”时发生了什么?
- String s1 = new String(“abc”)时又做了什么?
第二个问题是比较好回答的,根据官方文档:
new String(“abc”);
Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.
简单解释一下:
初始化一个新创建的String对象,换句话说,新创建的字符串是参数字符串的一个副本。除非确实需要一份副本,否则这种方法是不必要的,因为String是不可变的
这句话实际上透露出两个意思,
- 在编译器编译的时候,当编译器注意到参数为字符串常量时,即将字符串作为常量放在class文件中的常量区,并在类加载时放入运行时常量池中。
- 在new操作符被调用时,在java堆中创建一个新的对象,然后对象的内容为常量池里面对应字符串的一个拷贝。
而在String s2 = “abc”被编译的时候,先检查class文件中是否包含该字符串常量,如果包含,直接返回常量池中的对象。
因此,在调用new操作时,对象始终存在于堆中,而直接字符串赋值时对象实际上是存在于常量池中的,
所以比较结果肯定是false