StringBuffer何時初始化到常量池

  • 首先,在源代碼中用雙引號引起來的會自動進入常量池中(其實字符串對象是在堆中,然後常量池裏有個引用指向它,但是和直接說在常量池中似乎沒多大影響,下面也就這麼說了)
	String s1 = new StringBuffer("he").append("llo").toString();
	System.out.println(s1==s1.intern());//結果是true

這個he和llo都去池子裏面了。

  • 然後,intern()方法在JDK1.7做了一點小改進,之前的做法是如果字符串是首次出現,那麼將字符串複製到常量池中,然後返回常量池中的引用;JDK1.7的做法是如果是首次出現,那麼在常量池中記下這個字符串的位置,然後直接返回這個引用。我這點兒語文我自己都覺得稀爛。。。。
jdk1.6和jdk1.7下intern()方法的區別
隨便百度找的,基本就是《深入理解Java虛擬機》原文了。
文中說到"java"這個字符串並不是首次出現,它在這裏:
<img src="https://pic1.zhimg.com/v2-ce0ed85448ce4d79824c61d9e4705074_b.png" data-rawwidth="532" data-rawheight="127" class="origin_image zh-lightbox-thumb" width="532" data-original="https://pic1.zhimg.com/v2-ce0ed85448ce4d79824c61d9e4705074_r.png">在Oracle官網下載的JDK中rt.jar下可以找到這個類。當然如果你使用的是其他的JDK的話,可能並不是這樣子哦,比如我手裏這個JDK它是這樣的:
在Oracle官網下載的JDK中rt.jar下可以找到這個類。當然如果你使用的是其他的JDK的話,可能並不是這樣子哦,比如我手裏這個JDK它是這樣的:
<img src="https://pic1.zhimg.com/v2-9c328996c81cf72305752aa69e30a45c_b.png" data-rawwidth="575" data-rawheight="128" class="origin_image zh-lightbox-thumb" width="575" data-original="https://pic1.zhimg.com/v2-9c328996c81cf72305752aa69e30a45c_r.png">所以用我手裏這個去跑結果是這面這樣子的:
所以用我手裏這個去跑結果是這面這樣子的:
<img src="https://pic3.zhimg.com/v2-13973bbcd75e35af7ce54fdfbcbe6296_b.png" data-rawwidth="700" data-rawheight="145" class="origin_image zh-lightbox-thumb" width="700" data-original="https://pic3.zhimg.com/v2-13973bbcd75e35af7ce54fdfbcbe6296_r.png">
  • 解釋一下題主給的代碼的輸出
	String s2 = new StringBuffer("word").toString();
	System.out.println(s2==s2.intern());//結果是false
"word"在常量池中,s2肯定是指向的堆中的某塊地方,s2.intern()得到的是常量池中的,不是同一個,所以是false
	String s1 = new StringBuffer("he").append("llo").toString();
	System.out.println(s1==s1.intern());//結果是true

append一下和上面的區別在於,一開始"hello"並沒有在常量池中,在池中的是"he"和"llo",再結合上面關於intern()方法的介紹,應該很好理解吧。(測試這種東西最好用一些亂七八糟的東西甚至是中文,比如上面的"java",其他地方已經出現過了,指不定什麼地方也出現了"Hello")




StringBuffer的toString方法會調用new String, 在堆中新建對象。
 public synchronized String toString() {
        return new String(value, 0, count);
 }

String s2 = new StringBuffer("word").toString();
System.out.println(s2==s2.intern());//結果是false

1、word已經在字符串常量池中。
2、經過StringBuffer的toString以後,s2指向堆中新創建的對象。
3、s2.intern()拿到的是常量池中之前就存在的對象引用。
所以s2和s2.intern持有的不是同一個對象引用。

String s1 = new StringBuffer("he").append("llo").toString();
System.out.println(s1==s1.intern());//結果是true
1、hello不在字符串常量池中。
2、經過StringBuffer的toString以後,s1指向堆中新創建的對象,同時這個對象也被保存到常量池中。
3、s1.intern()去常量池中拿到的對象引用也正是剛剛新建的對象。
所以s1和s1.intern持有的是同一個對象引用。

發佈了38 篇原創文章 · 獲贊 109 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章