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。
【大寫加粗】以上是參考一些資料和自己的思考,歡迎批評指正。