今天在看一本書的時候注意到一個String的intern()方法,平常沒用過,隻是見過這個方法,也沒去仔細看過這個方法。是以今天看了一下。個人覺得給String類中加入這個方法可能是為了提升一點點性能,因為從常量池取資料比從堆裡面去資料要快一些。(個人感覺)
API上的那幾句關于這個方法,其實總結一句就是調用這個方法之後把字元串對象加入常量池中,常量池我們都知道他是存在于方法區的,他是方法區的一部分,而方法區是線程共享的,是以常量池也就是線程共享的,但是他并不是線程不安全的,他其實是線程安全的,他僅僅是讓有相同值的引用指向同一個位置而已,如果引用值變化了,但是常量池中沒有新的值,那麼就會新開辟一個常量結果來交給新的引用,而并非像線程不同步那樣,針對同一個對象,new出來的字元串和直接指派給變量的字元串存放的位置是不一樣的,前者是在堆裡面,而後者在常量池裡面,另外,在做字元串拼接操作,也就是字元串相"+"的時候,得出的結果是存在在常量池或者堆裡面,這個是根據情況不同不一定的,我寫了幾行代碼測試了一下。
先上結果:
1.直接定義字元串變量的時候指派,如果表達式右邊隻有字元串常量,那麼就是把變量存放在常量池裡面。
2.new出來的字元串是存放在堆裡面。
3.對字元串進行拼接操作,也就是做"+"運算的時候,分2中情況:
i.表達式右邊是純字元串常量,那麼存放在棧裡面。
ii.表達式右邊如果存在字元串引用,也就是字元串對象的句柄,那麼就存放在堆裡面。
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
結果:str1、str2、str3、str5都是存在于常量池,str4由于表達式右半邊有引用類型,是以str4存在于堆記憶體,而str5表達式右邊沒有引用類型,是純字元串常量,就存放在了常量池裡面。其實Integer這種包裝類型的-128 ~ +127也是存放在常量池裡面,比如Integer i1 = 10;Integer i2 = 10; i1 == i2結果是true,估計也是為了性能優化。