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。

 

【大寫加粗】以上是參考一些資料和自己的思考,歡迎批評指正。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM