String.intern()詳細分析,JDK1.8
阿新 • • 發佈:2018-11-05
前言
本文的測試環境是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