瞭解intern(),瞭解字符串常量池

intern()是String一個api,平時不常用,但是面試可能會考,掌握intern可避免被面試官問到時大眼瞪小眼的尷尬局面。

當一個String對象調用intern()方法時,會首先檢查字符串常量池中是否存在equals相等的字符串,若存在直接返回常量池中該字符串對象,否則創建該字符串對象並放入字符串常量池。

然而並不是所有創建的字符串都會進入常量池。下面直接貼代碼,每行代碼都通過備註的形式給出了運行結果和相關解釋。

          String a = new String("ab"); //開闢新的堆內存,存放字符串對象"ab",引用爲 a,同時"ab"進入字符串常量池
          String b = new String("ab"); //開闢新的堆內存,存放字符串對象"ab",引用爲 b,同時"ab"指向字符串常量池已有的對象
          String c = "ab"; //未開闢新的堆內存,直接將引用c指向了字符串常量池已有的"ab" 
          String d = "a" + "b"; //通過拼接靜態字符串的方式先檢查常量池中是否已有相等的對象,有則直接將引用指向和c相同的對象
          String e = "b"; //引用e指向一個新的字符串
          String f = "a" + e; //和e拼接將產生一個新的對象,即f指向新的內存地址
          
          System.out.println(c == d); //true  //d通過+拼接的是靜態字符串,非引用
          System.out.println(f == d); //false //f通過+拼接了一個引用相當於新創建了一個對象。
          
          //通過new 創建的字符串對象(a本身,b本身)不會進入字符串常量池
          System.out.println(a == a.intern()); //false,a沒有進入常量池,但是a.intern()已經進入,二者非同一對象
          System.out.println(c == c.intern()); //true,c本來就在字符串常量池,所以返回true
          System.out.println(b.intern() == a); //false,a沒有進入常量池,但是b.intern()已經進入且和a.intern()是同一個對象
          System.out.println(b.intern() == c); //true, b.intern()進入了常量池,c和該池子中的對象
          
          //通過+拼接靜態字符串得到的字符串對象會進入字符串常量池
          System.out.println(b.intern() == d); //true
          
          //非靜態字符串通過+拼接不會進入字符串常量池
          System.out.println(b.intern() == f); //false

          System.out.println(b.intern() == a.intern()); //true

大體總結3點:

1.new String的方式創建字符串對象,構造器參數進入字符串常量池,但是對象本身和常量池中的對象是兩個不同的對象。從而導致這種方式產生的字符串調用intern()方法和本身引用 == 將返回false。

2.靜態聲明的方式定義的字符串直接進入字符串常量池,如常量池已有該字符串,則直接指向已有字符串。這種方式產生的字符串調用intern()方法和本身引用==始終返回true。

3.+拼接靜態字符串創建的對象會進入字符串常量池,但是+拼接字符串引用就不會進入常量池。二者會導致完全不同的結果,前者調用intern()和自身==返回true,後者調用intern()和自身==返回false。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章