Java虚拟机中,每个类都有一个常量池,StringPool存在常量池中,对于A.StringA.intern()==B.StringB.intern()应该返回False~~可是我打出来的是True,Why?
阿神2017-04-17 11:18:07
每個類別中的常數池:
java的每一個類別都有一個常數池,這個常數池定義在.class檔案中有描述,包括整形、浮點型、字串、類別名稱、屬性名稱、方法宣告等。當jvm裝載.class檔案時,會裝載這些常數池信息,並按照JMM(java存儲模型)的定義,在方法區(即常說的PermGen Space[永久代])中開闢一塊內存空間,用以存儲這些常量。
要注意的是:
java同時會在方法區維持一個string pool,在裝載常數池的字串型常數時,會先將這些字串常數儲存到string pool中,然後傳回其引用給每個類別的常數池。
至於String.intern()方法,引用其JavaDoc:
A pool of strings, initially empty, is maintained privately by the class
String
.When the intern method is invoked, if the pool already contains a string equal to this
String
object as determined by the {@link #equals(Object)} method, then the string from the pool is returned. Otherwise, thisString
object is added to the pool and a reference to thisString
object is returned.It follows that for any two strings
s
andt
,s.intern() == t.intern()
istrue
if and only ifs.equals(t)
istrue
.
加粗標明的行也說明了java在方法區中會維持string pool。至於為什麼
A.StringA.intern()==B.StringB.intern()
會回傳true
相信你看了javaDoc會明白。
PS:不光String類別有JVM原生支援的常數池,Boolean、Byte、Character、Short、Integer、Long這六種原始類型包裝類,也實作了程式碼層級的常數池,具體可參考JDK源碼。
PPS:可供參考常數池
阿神2017-04-17 11:18:07
Java Doc:
"When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. the pool and a reference to this String object is returned. "
是說, 在呼叫str.intern()時, 首先去pool中找是否有equals(str)==true的字串. 找到後返回已存在於pool裡的字串, 否則把str加入pool中.
所以在pool裡, 相等的字串 只會有一份.
怪我咯2017-04-17 11:18:07
可能我問題有點問題~,「運行時常數池是方法去的一部分,Class檔案中除了有類別的版本、欄位、方法、介面等描述資訊外,還有一項資訊就是常數池,用於存放編譯器產生的各種字面量和符號引用,這部分內容在類別載入後存放在方法區的運行時常數池中。時常量池的一個引用
伊谢尔伦2017-04-17 11:18:07
如果字串StringA和StringB有著相同的內容,那麼上面的語句StringA.intern()==StringB.intern()
為true,因為他們指向的為同一個物件。
呼叫intern後,首先檢查字串常數池中是否有該物件的引用,如果存在,則將這個引用傳回給變量,否則將引用加入並傳回給變數。
具體可以參考Java中的字串常數池