一: String s = new String("ABC") VS String s = "abc"
String s = "abc" // 字元串字面量
String s = new String("abc"); 這個會無條件的在堆中建立一個新對象。
下面看字元串字面量。
首先,記住重要的一點是字元串對象是不可變的。這就意味着一旦建立,一個字元串對象就不能被改變(還是可以通過反射來改變, 反射可以改變使用方法的可見性)。
“字元串常量池”:事實上他是一用來儲存字元串對象引用的容器;即使字元串是不可變的,它仍然和Java中的其他對象一樣。對象都是建立在堆中,字元串也不例外。
是以字元串常量池仍然依靠堆,他們存儲的隻是堆中字元串的引用。因為字元串對象是不可變的,是以複制多個引用來“共享”這個字元串是安全的。
輸出:
下面看一下字元串常量池是如何工作的:
記憶體示意圖如下:

二:JDK 1.7後,字元串常量池的變化:
如果在常量池找不到對應的字元串,則不會再将字元串拷貝到常量池,而隻是在常量池中生成一個對原字元串的引用。簡單的說,就是往常量池放的東西變了:原來在常量池中找不到時,複制一個副本放到常量池,1.7後則是将在堆上的位址引用複制到常量池。
三: intern方法的作用:
public String intern(): 一個初始時為空的字元串池,它由類 String 私有地維護。當調用 intern 方法時,如果池已經包含一個等于此 String 對象的字元串(該對象由 equals(Object) 方法确定),則傳回池中的字元串。否則,将此 String 對象添加到池中,并且傳回此 String 對象的引用。
它遵循對于任何兩個字元串 s 和 t,當且僅當 s.equals(t) 為 true 時,s.intern() == t.intern() 才為 true。
傳回:
一個字元串,内容與此字元串相同,但它保證來自字元串池中。
------------------------------------------------------------------------------------------------
我們知道,一個Java程式運作後,String類會在記憶體的方法區中維護一個字元串池。對一個字元串調用intern()方法後,會先檢查池内是否有該字元串,若有則傳回;若沒有沒有則先建立再傳回,確定傳回的字元串已經以字面量的形式存在于池中。
測試代碼如下:
輸出: