真正理解String#intern

真正理解String#intern

intern作用

intern用來返回常量池中的某字符串,如果常量池中已經存在該字符串,則直接返回常量池中該對象的引用。
如果在常量池找不到對應的字符串,則不會再將字符串拷貝到常量池,而只是在常量池中生成一個對原字符串的引用。

案例分析

請先看字符串常量池,不然真的理解不透徹
jdk1.8測試:

案例一:

public static void main(String[] args) {
		//先在常量池放入1,再在堆上生成String obj,obj的char[] value指向常量池的1,棧上s1指向String obj
        String s1 = new String("1");
        //1已經在常量池了,所以這行代碼沒有任何意義
        s1.intern();
        //棧s2指向常量池的1
        String s2 = "1";
        //s1指向String obj, s2指向常量池,肯定不相等
        System.out.println(s1 == s2);//flase
		
		//用StringBuilder append 1和2,會把1和2放入到常量池中,堆中生成一個StringObj, obj的char[]value=12
		//注意此時常量池沒有12,value不是指向常量池了,而是把12存在自己的內存中,棧s3指向obj
        String s3 = new String("1") + new String("2");
        //此時常量池沒有12,他會把12的引用即String obj的引用放到常量池中(1.7以前是直接放12到常量池)
        s3.intern();
        //常量池有指向12的引用,把這個引用(即obj的地址)給s4
        String s4 = "12";
        //s3和s4都指向obj,所以相等
        System.out.println(s3 == s4);//true
    }

在這裏插入圖片描述

案例二:

 public static void main(String[] args) {
        String s1 = "hello";//棧s1指向常量池hello
        String s2 = " world";//棧s2指向常量池 world
        String s3 = s1+s2;//StringBuilder append hello和world,s3指向堆的obj,obj的char[]value存hello world
		//此時常量池沒有hello world,把s3的引用存入常量池
        s3.intern();//這行代碼如果移下一行結果就變了
        //s4指向常量池s3的地址
        String s4 = "hello world";
        System.out.println(s4 == s3);//true
    }

試着自己畫一下圖吧

案例三:

 public static void main(String[] args) {
 	  //toString裏面new String(char []value)
 	  //往常量池添加計算機,軟件這兩個字符串
 	  //堆中String obj的char[]value保存計算機軟件這個字符串,str1指向堆中obj
      String str1 = new StringBuilder("計算機").append("軟件").toString();
      //因爲此時常量池沒有計算機軟件,str1.intern()會把str1的引用添加到常量池並返回str1的引用,所以相等
      System.out.println(str1.intern()==str1);//輸出true
	  
	  //往常量池添加ja,va這兩個字符串
	  //因爲常量池已經有java這個字符串了,堆中String obj的char[]value指向常量池的java,str2指向obj
      String str2 = new StringBuilder("ja").append("va").toString();
      //str2.intern()返回java,而str2指向堆obj,地址不相等
      System.out.println(str2.intern() == str2);//輸出false
  }      

在這裏插入圖片描述

案例四:

 public static void main(String[] args) {
        String str1 = "a";//str1指向常量池a
        String str2 = "b";//str2指向常量池b
        String str3 = "ab";//str3指向常量池ab
        String str4 = str1 + str2;//str4指向堆String obj,obj的char[] value指向常量池ab
        String str5 = new String("ab");//str5指向堆String obj, obj的char[] value指向常量池ab

        System.out.println(str5 == str3);//f
        System.out.println(str5.intern() == str3);//t
        System.out.println(str5.intern() == str4);//f

        String a = new String("ab");//a指向堆String obj, obj的char[] value指向常量池ab
        String b = new String("ab");//b指向堆String obj, obj的char[] value指向常量池ab
        String c = "ab";//c指向常量池ab
        String d = "a" + "b";//d指向常量池ab (編譯期確定)
        String e = "b";//e指向常量池b
        String f = "a" + e;//f指向堆String obj,obj的char[] value指向常量池ab (StringBuilder實現)

        System.out.println(b.intern() == a);//f
        System.out.println(b.intern() == c);//t
        System.out.println(b.intern() == d);//t
        System.out.println(b.intern() == f);//f
        System.out.println(b.intern() == a.intern());//t

    }

參考

美團

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