今天在看一本書的時候注意到一個String的intern()方法,日常沒用過,只是見過這個方法,也沒去仔細看過這個方法。因此今天看了一下。我的以爲給String類中加入這個方法多是爲了提高一點點性能,由於從常量池取數據比從堆裏面去數據要快一些。(我的感受)安全
API上的那幾句關於這個方法,其實總結一句就是調用這個方法以後把字符串對象加入常量池中,常量池咱們都知道他是存在於方法區的,他是方法區的一部分,而方法區是線程共享的,因此常量池也就是線程共享的,可是他並非線程不安全的,他實際上是線程安全的,他僅僅是讓有相同值的引用指向同一個位置而已,若是引用值變化了,可是常量池中沒有新的值,那麼就會新開闢一個常量結果來交給新的引用,而並不是像線程不一樣步那樣,針對同一個對象,new出來的字符串和直接賦值給變量的字符串存放的位置是不同的,前者是在堆裏面,然後者在常量池裏面,另外,在作字符串拼接操做,也就是字符串相"+"的時候,得出的結果是存在在常量池或者堆裏面,這個是根據狀況不一樣不必定的,我寫了幾行代碼測試了一下。性能優化
先上結果:性能
1.直接定義字符串變量的時候賦值,若是表達式右邊只有字符串常量,那麼就是把變量存放在常量池裏面。測試
2.new出來的字符串是存放在堆裏面。優化
3.對字符串進行拼接操做,也就是作"+"運算的時候,分2中狀況:spa
i.表達式右邊是純字符串常量,那麼存放在棧裏面。線程
ii.表達式右邊若是存在字符串引用,也就是字符串對象的句柄,那麼就存放在堆裏面。code
String str1 = "aaa"; String str2 = "bbb"; String str3 = "aaabbb"; String str4 = str1 + str2; String str5 = "aaa" + "bbb"; System.out.println(str3 == str4); // false System.out.println(str3 == str4.intern()); // true System.out.println(str3 == str5);// true
結果:str一、str二、str三、str5都是存在於常量池,str4因爲表達式右半邊有引用類型,因此str4存在於堆內存,而str5表達式右邊沒有引用類型,是純字符串常量,就存放在了常量池裏面。其實Integer這種包裝類型的-128 ~ +127也是存放在常量池裏面,好比Integer i1 = 10;Integer i2 = 10; i1 == i2結果是true,估計也是爲了性能優化。對象