亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JDK7中String.Intern()方法的疑問

JDK7中String.Intern()方法的疑問

HUWWW 2019-09-19 13:25:29
Strings1=newString("aa")+newString("bb");s1.intern();Strings2="aabb";System.out.println(s1==s2);//true我已經了解,JDK6中intern()會在常量池中不存在的情況下直接拷貝值放入常量池,而JDK7是會把堆中的引用放入常量池。這段代碼中的字面量"aa""bb""aabb"在編譯器就已經放入常量池中了,很多文章都說成執行到Strings2="aabb"才把“aabb”放入常量池,我認為是不對的。所以在s1.intern()這個操作應該是沒有產生任何副作用的,s1仍然指向堆中的一個對象,s2仍然指向常量池中的一個對象。但實際結果卻為true,而且把Strings2="aabb"移動到s1.intern()前面,結果就是我所預期的false。到底是為什么呢?
查看完整描述

2 回答

?
MMTTMM

TA貢獻1869條經驗 獲得超4個贊

先說點別的:
這里的字符串拼接沒有被優化
"xxx"這樣的字面量聲明自帶intern
不同版本的java效果各種不一樣
一般的用法是Stringx=x.intern(),因為可能會返回常量池里的引用
intern屬于用時間換空間,一般也很少用到…
編譯期沒有字符串常量池,字符串常量池是運行期的東西,也就是說直到某個字符串字面量聲明或者intern之前,這個字符串不會進入字符串常量池中
再說你這個例子:
如果s1.intern()發生在s2的聲明之前,s1進常量池,s2的聲明自帶intern,從常量池里找到s1賦值給自己,于是和s1是同一個引用
反過來,s2先聲明,進常量池,s1需要計算,得到一個新的字符串,和s2就不是同一個了,這時候如果做s1.intern()==s2還是true
                            
查看完整回答
反對 回復 2019-09-19
?
POPMUISE

TA貢獻1765條經驗 獲得超5個贊

涉及到更深入的類加載機制原答案比較混亂,我整理一下就是:1.查看字節碼文件中可以看到,定義一個字面量的Strings2="aabb"對象,其實是存儲了2個內容,一個是UTF8aabb,一個是String對象指向這個UTF8,這個是重點,使用常量池中的數據,實際使用的是這個String對象。2.加載類的時候會讀取字節碼文件中Constantpool里的內容放入運行期常量池,但這個時候只創建了UTF8aabb這個對象(C中的Symbol類型),配套的String對象是懶加載的,只有當第一使用到這個常量的時候才會在常量池中去創建這個String對象。3.再結合問題中的代碼,程序開始執行后,常量池中已經有"aa""bb""aabb"3個UTF8對象,但是并沒有可用的String對象。當執行完第一行代碼,會創建常量池中的"aa""bb"的String對象;當程序執行到s1.intern();時,常量池中并不存在"aabb"這個String對象,于是將s1的引用放入常量池作為String對象,后面代碼再去常量池獲取這個字面量的時候,返回的就是s1的地址,所以s1==s2。4.推測,上面這種情況,類加載時候創建的"aabb"Symbol對象就無用了,未證實。5.當先執行Strings2="aabb";的時候,會直接去常量池中獲取對象,發現常量池中的String對象不存在,于是創建一個,指向常量池中的UTF8aabb對象。下一步再執行在s1.intern();的時候,發現常量池中已經存在,放不進去了,所以結果是s1指向堆中的一個對象,s2指向常量池中的一個對象,2者并不相等。
查看完整回答
反對 回復 2019-09-19
  • 2 回答
  • 0 關注
  • 224 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號