1. 程式人生 > >String.intern()詳細分析,JDK1.8

String.intern()詳細分析,JDK1.8

前言

  本文的測試環境是JDK1.8。

  String.intern()分析在文中偏後

一.建立字串分析

1.直接使用雙引號建立字串

 判斷這個常量是否存在於常量池,
  如果存在,
   判斷這個常量是存在的引用還是常量,
    如果是引用,返回引用地址指向的堆空間物件,
    如果是常量,則直接返回常量池常量,
  如果不存在,
    在常量池中建立該常量,並返回此常量

    String a1 = "AA";//在常量池上建立常量AA
    String a2 = "AA";//直接返回已經存在的常量AA
    System.out.println
(a1 == a2); //true
    String a3 = new String("AA");    //在堆上建立物件AA
    a3.intern(); //在常量池上建立物件AA的引用
    String a4 = "AA"; //常量池上存在引用AA,直接返回該引用指向的堆空間物件,即a3
    System.out.println(a3 == a4); //true,如果這個例子不理解,請看完整篇文章再回來看這裡

2.new String建立字串

 首先在堆上建立物件(無論堆上是否存在相同字面量的物件),
 然後判斷常量池上是否存在字串的字面量,
  如果不存在
   在常量池上建立常量
  如果存在
   不做任何操作

    String a1 = new String("AA");
    String a2 = new String("AA");
    System.out.println(a1 == a2); //false
    //如果常量池上不存在常量AA,也不存在引用AA,則建立常量AA
    String a1 = new String("AA");
    System.out.println(a1 == a1.intern()); //false

3.雙引號相加

 判斷這兩個常量、相加後的常量在常量池上是否存在
  如果不存在
   則在常量池上建立相應的常量
  如果存在
   判斷這個常量是存在的引用還是常量,
    如果是引用,返回引用地址指向的堆空間物件,
    如果是常量,則直接返回常量池常量,

    String a1 = "AA" + "BB";//在常量池上建立常量AA、BB和AABB,並返回AABB
    //常量池上存在常量AABB
    String a2 = "AABB";
    String a3 = "AA" + "BB";
    System.out.println(a2 == a3); //true
    //常量池上存在引用AABB
    String a4 = new String("AA") + new String("BB"); //在堆上建立物件AA、BB和AABB,在常量池上建立常量AA和BB
    a4.intern();
    String a5 = "AA" + "BB";
    System.out.println(a4 == a5); //true

4.兩個new String相加

 首先會建立這兩個物件以及相加後的物件
 然後判斷常量池中是否存在這兩個物件的字面量常量
  如果存在
   不做任何操作
  如果不存在
   則在常量池上建立對應常量

    //常量AA不存在,所以第一步在常量池中建立了常量AA
    String a2 = new String("AA") + new String("BB");
    String a3 = new String("A")+new String("A"); //建立物件AA
    System.out.println(a3 == a3.intern()); //false
    //只在堆上建立AABB物件,沒有在常量池中建立常量AABB
    String a2 = new String("AA") + new String("BB");
    System.out.println(a2 == a2.intern()); //true

5.雙引號字串與new String字串

 首先建立兩個物件,一個是new String的物件,一個是相加後的物件
 然後判斷雙引號常量與new String的字面量在常量池是否存在
  如果存在
   不做操作
  如果不存在
   則在常量池上建立物件的常量

    String a1 = "AABB";
    String a2 = "AA" + new String("BB");
    System.out.println(a1 == a2.intern());//true
    System.out.println(a2 == a2.intern()); //false

二.String.intern()分析

 判斷這個常量是否存在於常量池。
  如果存在
   判斷存在內容是引用還是常量,
    如果是引用,
     返回引用地址指向堆空間物件,
    如果是常量,
     直接返回常量池常量
  如果不存在,
   將當前物件引用複製到常量池,並且返回的是當前物件的引用

    String a1 = "AA";
    System.out.println(a1 == a1.intern()); //true
    String a2 = new String("B") + new String("B");
    a2.intern();
    String a3 = new String("B") + new String("B");
    System.out.println(a2 == a3.intern());//true
    System.out.println(a3 == a3.intern());//false
    String a4 = new String("C") + new String("C");
    System.out.println(a4 == a4.intern()); //true

三.總結

1.只在常量池上建立常量

    String a1 = "AA";

2.只在堆上建立物件

    String a2 = new String("A") + new String("A");

3.在堆上建立物件,在常量池上建立常量

    String a3 = new String("AA");

4.在堆上建立物件,在常量池上建立引用

    String a4 = new String("A") + new String("A");//只在堆上建立物件AA
    a4.intern();//將該物件AA的引用儲存到常量池上

5.在堆上建立物件,在常量池上建立常量,在常量池上建立引用(不可能)

    String a5 = new String("A") + new String("A");//只在堆上建立物件
    a5.intern();//在常量池上建立引用
    String a6 = "AA";//此時不會再在常量池上建立常量AA,而是將a5的引用返回給a6
    System.out.println(a5 == a6); //true

6.

常量池上常量 常量池上引用 堆上物件
常量池上常量 X 不共存 共存
常量池上引用 不共存 X 共存
堆上物件 共存 共存 X

四.練習

         String aa = "AA";//設定常量AA到常量池
         String bb = "BB";//設定常量BB到常量池
         String ccdd = "CC"+"DD";//設定常量CCDD到常量池
         String neeff = new String("EE")+new String("FF");//設定EE和FF到常量池。並且新增EE、FF和EEFF物件到堆
         String aabb = aa+bb;//新增AABB物件到堆
         String gghh = "GG"+new String("HH");//設定GG和HH常量到常量池,設定HH和GGHH物件到堆
//         aa.intern();//啥事都不做,返回AA常量
//         ccdd.intern();//啥事都不做,返回CCDD常量
//         neeff.intern();//新增EEFF物件的引用到常量池,並返回EEFF物件
//         aabb.intern();//新增AABB物件的引用到常量池,並返回AABB物件
//         gghh.intern();//新增GGHH物件的引用到常量池,並返回GGHH物件
         System.out.println(aa.intern()==aa); //true
         System.out.println(neeff.intern()=="EEFF");//true
         System.out.println("EEFF"==neeff);//true
         String nccdd = new String("CCDD");
         System.out.println(ccdd==nccdd);//false
         System.out.println(ccdd==nccdd.intern());//true
         System.out.println(aabb.intern()==aabb);//true
         System.out.println(gghh==gghh.intern());//true