使用intern 方法測試String 對象的創建過程

實驗背景:

    在看《深入理解java虛擬機》中的介紹字符串常量池的下段文件,產生了一些疑問,故做此實驗。

 

實驗環境: jdk1.8

測試代碼1:

public static void main(String[] args) {
		String s1=new StringBuilder("計算機").append("技術").toString();
		String s2=new StringBuilder("計算機").append("技術").toString();
		String s3=new StringBuilder("編程思想").toString();
		System.out.println(s2.intern()==s2);
		System.out.println(s2=="計算機技術");
		System.out.println(s2.intern()=="計算機技術");
		System.out.println(s1.intern()==s1);
		System.out.println(s1.intern()==s2);
		System.out.println(s2.intern()==new String("計算機技術"));
        System.out.println(s3.intern()==s3);
		System.out.println(s3.intern()=="編程思想");
	}

測試1結果:true   true    true    false   true     false   false   true


 運行過程猜想:s1 創建了一個用StringBuilder創建了一個 "計算機技術"的String對象放在堆中,常量池中放入了兩個字符串"計算機"、"技術",並沒有放入"計算機技術”此字符串。因爲已有了"計算機"、"技術" 這兩個字符串,所以s2的過程僅僅在堆中創建了一個 "計算機技術"的String對象。     s3的創建過程類似於new String("編程思想"),先在常量池中放入字符串“變成思想”,再在堆中創建了一個“編程思想"的String對象。  

結果分析:s2.intern()方法執行時,因常量池中並沒有"計算機技術”此字符串,所以此方法在常量池中創建了一個 "計算機技術”字符串的引用,此引用指向 s2,所有 第一個結果爲true.

        在比較s2.intern() 和 “計算機技術” 時,因前面運行了一次s2.intern()方法,所以常量池中存在“計算機技術”此字符串常量(引用,這裏指向s2所指的對象),故也返回true,

      同理第三個條也返回true。

      因爲常量池中已有“編程思想”這個常量的引用,s1.intern()方法返回的即此引用所指的對象,所以第四條false,第五條true。

      s2.intern()和new String()對比肯定返回false。第六條false。

      s3在創建的時候已經向常量池中放入“變成思想”常量,所以s3.intern()返回的即常量池中的對象,不是s3這個對象。因此第七條false,第八條true.

 

測試代碼2:

public static void main(String[] args) {
		String s1=new StringBuilder("計算機").append("技術").toString();
		String s2=new StringBuilder("計算機").append("技術").toString();
		
		System.out.println("計算機技術"==s2.intern());
		System.out.println(s2.intern()==s2);
		System.out.println(s2=="計算機技術");
		System.out.println(s2.intern()=="計算機技術");
		System.out.println(s1.intern()==s1);
		System.out.println(s1.intern()==s2);
		System.out.println(s1.intern()=="計算機技術");
	}

運行結果:true  false  false  true  false  false  true

運行過程猜想:相比於測試1 ,這裏主要把"計算機技術"==s2.intern() 這一步放在最前面,並把“計算機技術”放在左邊,運行到這一步時,jvm會先把“計算機技術” 放入常量池 ,再執行s2.intern()方法。

結果分析:因爲s1、s2都還未執行intern()方法,所以常量池中不會有引用指向這兩個對象,而是直接保存的是"計算機技術"這個常量,故運行結果爲以上。

 

 

總結:用StringBuilder拼接字符串的時候,不會在常量池中保存最後拼成的結果,使用intern()方法,若常量池中沒有此字符串或者其引用則會在常量池中保存此引用,並指向堆中對象(這種對象是否會被gc???),

另外再提一下,使用StringBuilder拼接的好處是String是final類,每次拼接都會再創建一個對象。

使用String s="嘻嘻"+"哈哈"+"嘿嘿";  其實編譯器會優化成 s="嘻嘻哈哈嘿嘿"; 即會在常量池中放入了一個常量。


 

 

 

 

 

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