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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章