今天在看一本書的時候注意到一個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,估計也是為了性能優化。
