new String("abc"),到底在不在常量池中存储"abc"?

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。

 

【大写加粗】以上是参考一些资料和自己的思考,欢迎批评指正。

posted @ 2020-08-04 22:31  XJXia_Post  阅读(1161)  评论(0编辑  收藏  举报