1. 程式人生 > >String的intern()方法 與執行時常量池(方法區)

String的intern()方法 與執行時常量池(方法區)

String的intern()方法 與執行時常量池(方法區)

在你看這篇文章時我假設你已經瞭解jvm記憶體
1.String.intern()是一個Native方法,作用是:如果字串常量池存在字串相等(equals() )的字串物件,就返回此常量池中的String物件。否則將String物件新增到常量池中,並返回此String物件的引用。
2.Jdk1.6及其之前的版本,字串常量池分佈在永久帶(方法區)中,Intern()把首次遇到的字串複製到常量池中,返回的也是常量池中例項的引用。
3.jdk1.7以後字串常量池移到了堆中,Intern()不再複製例項,只是在常量池中記錄例項的引用,因此返回的引用和下面StringBuilder建立的例項是同一個。

  public class Main {
    public static void main(String[] args) {
        String str1 = new StringBuilder("hu").append("xin").toString();  //new的物件放在堆裡
        System.out.println(str1 == str1.intern());
      }
  }

此方法jdk1.6及其以前返回 false
jdk1.7及其以後返回 true
上面程式碼如果直接new String("hu")或者去掉上面的.append("xin")

產生字串,就會得到false,因為在類載入的過程中,確實在執行時常量池中建立了一個"hu"物件,而在程式碼執行過程中又在堆中建立了一個String物件。這是兩個例項。

註解:JDK1.7為什麼要把字串常量池移動到堆裡面

在Java 7之前,JVM 將Java字串池放在永久代PermGen(方法區)中,該空間具有固定的大小 - 它不能在執行時擴充套件,也不在垃圾回收的範圍內。

在PermGen(方法區)中實現字串的風險是,如果我們定義太多字串,JVM可能報OutOfMemory錯誤。

從Java 7開始,Java字串池儲存在堆空間中,這是 JVM的垃圾收集範圍內。這種方法的優點是降低了OutOfMemory錯誤的風險,因為未引用的字串將從池中刪除,從而釋放記憶體。

字串總結

public class Main {
public static void main(String[] args) {
    String str11 = new StringBuilder("hu").append("xin").toString();  //物件放在堆裡--採用new 建立的字串物件不進常量池
    String str22 = new StringBuilder("hu").append("xin").toString();  //物件放在堆裡--採用new 建立的字串物件不進常量池
    System.out.println(str11 == str22);
    System.out.println(str11 == str11.intern());        //第一次呼叫Intern發現字串不存在常量池,(1.7 將str11的引用放入常量池)
    System.out.println(str11 == str22.intern());        //第二次呼叫Intern發現字串存在常量池裡,返回常量池裡的引用

    final String str1 = "a";
    String str2 = "b";
    String str3 = "ab";
    String str4 = "a" + str2;                  //字串相加含有變數則不會進入常量池中
    String str5 = new String("ab");
    String str6 = "a"+"b";                     //字串相加的時候,都是靜態字串的結果會新增到常量池
    String str7 = str1 +"b" ;                   //對final變數的訪問在編譯期間都會直接被替代為真實的值 相當於靜態字串

    System.out.println(str5 == str3);
    System.out.println(str5.intern() == str3);
    System.out.println(str5.intern() == str4);
    System.out.println(str5.intern() == str6);
    System.out.println(str5.intern() == str7);

    }
}

結果

false
true
true
false
true
false
true
true

1.採用new 建立的字串物件不放入常量池
2.字串相加的時候,都是靜態字串的結果會新增到常量池,如果其中含有變數(如str1)則不會放入常量池中
3.對final變數的訪問在編譯期間都會直接被替代為真實的值 相當於靜態字串