String類中intern方法的原理分析
一,前言
昨天簡單整理了JVM記憶體分配和String類常用方法,遇到了String中的intern()方法。本來想一併總結起來,但是intern方法還涉及到JDK版本的問題,內容也相對較多,所以今天就彌補昨天缺失的知識點。
二,String.intern()
先來看下網上流行的關於intern()方法的示例程式碼:
public static void main(String[] args) { String s = new String("1"); s.intern(); String s2 = "1"; System.out.println(s == s2); String s3 = new String("1") + new String("1"); s3.intern(); String s4 = "11"; System.out.println(s3 == s4); }
列印結果是:
JDK6:false,false
JDK7:false,true
首先我們先來回顧一個概念:
- jdk6及以前中常量池是存放在方法區中。
- jdk7以後常量池移動到堆中。
為什麼要移動?常量池主要是儲存載入類的資訊,編譯器生成的字面量和符號引用等。它的大小大約只有4M,如果大量使用intern()方法,便會造成常量池內除溢位的情況,同時GC回收也有一定的困難度。而且在jdk8以後,連Perm區域都沒有了,被替換成了元區域。
接著我們再來說說上面兩種情況不同的結果。
JDK6:
String s = new String("1");
1,這句程式碼實際上是生成兩個例項物件,先在常量池中宣告為1的字元物件,再通過關鍵字new生成1的字元物件並被s引用。
2,接著s.intern();
先在常量池中查詢是否有相應的字串存在,如果有,直接返回引用,否則,在常量池中生成相應的字串並返回引用。
3,而String s2 = "1";
是屬於符號引用,直接在常量池中生成。
4,最後判斷s 是否與s2相等,通過上面的分析,s指向的是通過關鍵字new出來的在堆中的字元物件,而s2是符號引用的在常量池中的字元物件,所以返回的結果為false。如下圖所示:
String s3 = new String("1") + new String("1");
同理這句程式碼實際上也是產生2個字元物件,其原理和上面分析是一樣的,而最後判斷s3與s4的值,結果還是一個堆中的s3與常量池中的s4比較,那返回的結果必然是false。
JDK7:
String s1 = new String("1");
s1.intern();
String s2 = "1";
System.out.println(s == s2);
1,這一部分程式碼與jdk6中的分析是類似的,但唯一不同的是s1.intern();
返回的是在常量池中的引用,並不會在常量池中複製一份再返回引用。
String s2 = "1";
與s1.intern();
指向的是同一個引用。
2,最後比較s與s2的值,s是堆中,s2是常量池中,因而返回結果為false。
3,接著我們再來看下面一段程式碼:
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
我們先來分析第一句程式碼,同樣是生成兩個字元物件,先在常量池中生成為1的字元物件,再在堆中生成s3為11的字元物件。接著s3.intern();
執行便去常量池中查詢是否存在為11的字元物件,但是發現沒有。這個時候在jdk7及之後便不會再複製一份為11到常量池中,而是直接返回堆中11的字元物件的引用。所以它與s3的引用地址是相同的。
String s4 = "11";
這句程式碼是符號引用,直接去常量池中建立,但是發現池中已經存在為11的字元物件的引用,因此直接返回該引用。最後判斷s3與s4是否相等,因為它們之間的引用的相同的,所以返回的結果為true。如下圖所示:
三,總結
1,對於常量池的概念要注意jdk6與jdk7之間的變化。
2,intern()方法在不同jdk版本之間的變化,jdk7之後如果常量池中不存在,不會再複製一份到常量池中,而是返回堆中的存在的引用地址。
3,jdk6常量池在方法區中,jdk7常量池在堆中,jdk8取消方法區,替換成元區域。
最後關於String類中intern方法就介紹這裡,其實從實際開發工作中,我們只需要瞭解jdk7及以後版本的原理就可以了,畢竟現在市面上很少再用jdk6版本。但是這裡總結出來也是為了更方便的參照理解,同時也涉及到一些關於JVM記憶體的相關知識,本篇部落格是接著上一篇內容的缺失的知識點。
以上內容均是自主學習總結的,如有不適之處還請留言(郵箱)指教。
感謝閱讀