String str = new String("Hello World");
问之:这行代码到底有没有在字符串常量池中创建“Hello World”字符串呢?
答曰:有。
问之:为什么?
答曰:先看String类的构造函数。
public String(String original){ //body }
在这个过程中,“Hello World"作为形参传递给original,这个过程相当于 String original = “Hello World",因此,在常量池中创建字符串“Hello World"。
之后,我们都知道,new的对象都存在在堆中,因此,new String(“Hello World")在堆中创建了对象,并将其赋值给str,即 String str = 。
这么一来,在字符串常量池中存在字符串“Hello World",在堆中存在对象“Hello World"。
然鹅, str == s 并不为true。因为字符串常量池在方法区中(在JDK 1.8之后就放在堆中开辟的一块内存中了),new的对象在堆中,方法区与堆是不同的内存空间。
因此, str == s为false。
String str = new String("Hello World");
String s = "Hello World";
问曰:不是有个intern()函数吗?
答之:Of course。
问曰:那下面的代码str == s 返回true了吗?
String str = new String("Hello World"); str.intern(); String s = "Hello World";
答之:Of course not。因为前面已经说过了,String str = new String(“Hello World");语句已经在常量池中创建了“Hello World",那么str.intern();就不起作用啦。所以,等效于不加这一句。
问曰:那str.intern();就是鸡肋了吗?
答之:存在即合理。请往下看
String str = new String("Hello") + new String(" World"); str.intern(); // 注意这一行的顺序,要在下一行之前。否则,也不起作用啦。 String s = "Hello World";
好了,这次终于返回true了(在JDK1.7及以后),因为,常量池中虽然存在"Hello"和" World",但是不存在"Hello World",这个只有在堆中存在。
JDK 1.7以后,在堆中存在而不在常量池中存在的字符串,在常量池中存放其引用,因此str和指向同一块内存。
JDK 1.7以前,由于常量池不在堆中,那么存放的还是字符串本身,因此仍返回false。
【大写加粗】以上是参考一些资料和自己的思考,欢迎批评指正。