java的intern问题请教

Uranus_yyang 2019-04-23 08:03:31
今天刚看了《深入理解java虚拟机》的第二章,在string这里被难住了。


String str1=new StringBuilder("hello ").append("world").toString();
System.out.println(str1==str1.intern())

这里结果为true,然后若改成:
String str1=new StringBuilder("hello world").toString();
System.out.println(str1==str1.intern());


结果为false。
这里有点不太理解。一是append为什么会带来这种差异。二是对于第一个结果,书上解释说"jdk1.7的intern()实现不会再复制实例,只是在常量池中记录首次出现的实例引用。因此intern()返回的引用和由StringBuilder()创建的那个字符串实例是同一个“。按这种解释,第二个结果应该也是true啊?
...全文
92 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
Uranus_yyang 2019-04-23
  • 打赏
  • 举报
回复
引用 1 楼 wildyy 的回复:
先解释下intern方法: 这个方法会返回字符串常量池中的与调用该方法字符串对象具有相同字符串值的对象。 什么情况下会在字符串常量池创建字符串: 1.出现引号字符串的情况,例如String s = "a"或s = "a" + "b"。(这个"a" + "b"实际上是在常量池创建"ab"字符串,如果还想了解具体原因,可以去看下生成的字节码。)又或者楼主所使用的new StringBuilder("hello")。 2.出现调用String.intern方法的情况。这种情况下首先判断字符串常量池是否存在对应的字符串,如果不存在,则将本对象加入常量池,并返回本对象,如果存在,则返回常量池中的对象。 下面看楼主的两种操作: 第一个,new StringBuilder("hello"),这一步会在字符串常量池先创建"hello"字符串对象,然后将"hello"对象中的value(String中字符串实际是使用char[]保存的,字段名叫value)拷贝给StringBuilder对象的value字段(这个字段是StringBuilder中保存字符串的,也是char[])。这一步会在常量池创建"hello",接下来调用append("world"),这一步首先在字符串常量池创建"world"字符串对象,然后同样将"world"的value字段拷贝到StringBuilder的value。这一步会在常量池创建"world"。接下来调用toString,这个方法会new一个String对象,而传进去的是char[],你可以看看String(char[])这个构造方法,只是将char[]赋给value字段,故而出现了存在这个字符串,而字符串常量池不存在,再调用intern,就将本对象加在字符串常量池了,所以第一步的intern返回的就是本对象,所以为true。 第二个,同第一个的创建过程,所以字符串常量池有了"hello"这个字符串,然后调用StringBuilder.toString,上面也有解释,是new了一个String对象,其值为"hello",调用它的intern,因为"hello"在字符串常量池已经存在,所以返回常量池中的"hello",与你调用toString得到的就不是一个对象,所以为false。 其实从这个过程也能明白为什么说StringBuilder的效率高,它就是因为跳过了在字符串常量池创建字符串的过程。但也不是所有情况下都是它的效率高,我们也没有必要时时刻刻都用它,有些时候编译器是会帮我们去自动调用它,这个具体可以多看下关于字符串操作的字节码。
解释得很详细!太感谢了!
wildyy 2019-04-23
  • 打赏
  • 举报
回复
先解释下intern方法: 这个方法会返回字符串常量池中的与调用该方法字符串对象具有相同字符串值的对象。 什么情况下会在字符串常量池创建字符串: 1.出现引号字符串的情况,例如String s = "a"或s = "a" + "b"。(这个"a" + "b"实际上是在常量池创建"ab"字符串,如果还想了解具体原因,可以去看下生成的字节码。)又或者楼主所使用的new StringBuilder("hello")。 2.出现调用String.intern方法的情况。这种情况下首先判断字符串常量池是否存在对应的字符串,如果不存在,则将本对象加入常量池,并返回本对象,如果存在,则返回常量池中的对象。 下面看楼主的两种操作: 第一个,new StringBuilder("hello"),这一步会在字符串常量池先创建"hello"字符串对象,然后将"hello"对象中的value(String中字符串实际是使用char[]保存的,字段名叫value)拷贝给StringBuilder对象的value字段(这个字段是StringBuilder中保存字符串的,也是char[])。这一步会在常量池创建"hello",接下来调用append("world"),这一步首先在字符串常量池创建"world"字符串对象,然后同样将"world"的value字段拷贝到StringBuilder的value。这一步会在常量池创建"world"。接下来调用toString,这个方法会new一个String对象,而传进去的是char[],你可以看看String(char[])这个构造方法,只是将char[]赋给value字段,故而出现了存在这个字符串,而字符串常量池不存在,再调用intern,就将本对象加在字符串常量池了,所以第一步的intern返回的就是本对象,所以为true。 第二个,同第一个的创建过程,所以字符串常量池有了"hello"这个字符串,然后调用StringBuilder.toString,上面也有解释,是new了一个String对象,其值为"hello",调用它的intern,因为"hello"在字符串常量池已经存在,所以返回常量池中的"hello",与你调用toString得到的就不是一个对象,所以为false。 其实从这个过程也能明白为什么说StringBuilder的效率高,它就是因为跳过了在字符串常量池创建字符串的过程。但也不是所有情况下都是它的效率高,我们也没有必要时时刻刻都用它,有些时候编译器是会帮我们去自动调用它,这个具体可以多看下关于字符串操作的字节码。
哦呼 2019-04-23
  • 打赏
  • 举报
回复
https://blog.csdn.net/soonfly/article/details/70147205
你看看

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧