Java String intern() 解析

String 在 java 中是一個使用最頻繁的類,也是佔據內存最大的類,合理的優化 String 對象,能夠節省寶貴的內存資源。java

String#intern()

在每次賦值的時候使用,若是常量池中有相同值,就會重複使用該對象,返回對象引用,這樣一開始的對象就能夠被回收掉。數組

例子

上一段代碼優化

String s1 = "abc";
String s2 = new String("abc");
String s3 = s2.intern();

System.out.println("1:" + (s1 == s2));
System.out.println("2:" + (s2 == s3));
System.out.println("3:" + (s1 == s3));
System.out.println("================================");
String s4 = new String("1") + new String("1");
String s5 = "11";
System.out.println("4:" + (s4 == s5));
String s6 = s4.intern();
System.out.println("5:" + (s4 == s5));
System.out.println("6:" + (s5 == s6));
System.out.println("7:" + (s4 == s6));

結果是:指針

1:false
2:false
3:true
================================
4:false
5:false
6:true
7:false

解析

理解這一塊的核心在於這段代碼運行是分爲2個階段的,1.類加載 2.類執行code

1.類加載時(注:JDK 1.7 以後,常量池合併在堆中):對象

  • 字符串常量:在常量池中開闢一個空間,存放字符串對象
  • 字符串變量:會把new String() 中的字符串放入常量池中

2.類運行時:在堆內存中開闢一個空間存放該對象,String 類中的 char 數組引用常量池對象,返回堆內存中的地址給變量引用。內存

若是調用 intern() 方法,就會去字符串常量池中查看是否有等於該對象字符串的引用,若是有,就返回返回字符串常量池中的引用資源

額外注意 s4 動態生成的字符串
動態生成的字符串直接在堆上建立,字符串常量池沒有,當調用 intern 方法獲取引用時,則會去常量池中判斷是否有相等的引用,若是有返回引用,若是沒有則放入。字符串

intern 方法 不改版自己的指針引用,從7就能夠看出,s4調用intern 後與 s6 比較,仍不相等。變量

總結

  • 非動態生成的字符串,在類加載時就已經將字符串對象放入常量池中,運行時視對象是常量仍是變量賦值:

    • 常量:直接執行常量池
    • 變量:先指向堆開闢的new 空間,堆再指向常量池
  • 動態生成的字符串,直接在堆上建立,調用 intern 方法時,會去常量池中判斷,若是有返回地址,若是沒有,放入,返回。

intern 方法,若是常量池中沒有匹配的字符串,就將本身放入而後返回,不然返回字符串對象在常量池中的地址。

思考

爲何相等 ?

String a =new String("abc").intern();
String b = new String("abc").intern(); 
if(a==b) { System.out.print("a==b");}
相關文章
相關標籤/搜索