stringbuilder输出文件为什么只有最后一行_一道看了答案都不知道为什么的面试题...

题目

经常看到一道面试题,题目如下,每次都是猜答案,几乎每次都猜错。看到答案后,也无法解释为什么,直到最近学习了 JVM 相关的知识,才理解透彻。

// 运行环境为JDK版本1.8public static void main(String[] args) {    String  s1 = new String("1");    s1.intern();    String s2 = "1";    System.out.println(s1 == s2);   // false    String s3 = new String("1") + new String("1");    s3.intern();    String s4 = "11";    System.out.println(s3 == s4);   // true}

这道题在 JDK1.8 的环境下运行(注意:这道题与 JDK 的版本密切相关,不同版本会有不同的答案),结果分别为 false、true。s1 和 s2 的比较结果,很容易判断,而对于 s3 和 s4 的比较结果,则就不太好理解了,接下来将从字节码和 JVM 内存结构的角度来解释一下运行结果。

intern()

intern()方法是 String 类提供的一个方法,当调用一个字符串对象 s 的 intern()方法时,会先判断字符串常量池中是否存在 s 所表示的字面量(这个判断过程使用的是字符串的 equals()进行比较的,即比较的是字符串的内容),如果字符串常量池中存在该字面量,则 intern()方法不做任何操作,直接返回常量池中该字面量的地址;如果字符串常量池中不存在该字面量,那么就将该字面量放入到字符串常量池中(也就是在常量池中造了一个"对象"),然后返回常量池中该字面量的地址。

这里的关键点在于字符串常量池,在 JVM 虚拟机规范中,字符串常量池是属于方法区的一部分,而方法区只是 Java 虚拟机规范中的概念,具体如何去实现方法区,是由各个虚拟机厂商自己决定的。并且同一厂商实现的虚拟机,在不同版本中也存在不同的区别。例如 HotSpot 虚拟机,在 JDK1.6 中,整个方法区都是在永久代(PermGem)实现的;到了 JDK1.7 中,方法区也是在永久代(PermGem)实现的,但与 JDK1.6 不同的是,将方法区中的运行时常量池和字符串常量池放到了堆空间,而其他部分在还是在永久代中;再到 JDK1.8 时,则是用元空间(Metaspace)实现的方法区,即用元空间(Metaspace)取代了永久代(PermGem),元空间使用的是直接内存,但是方法区中的运行时常量池和字符串常量池依旧是在堆空间,这和 JDK1.7 是相同的。如下面的示意图所示。

0f807e12471a4320fd54b51dbf47e6c8.png

从 JDK1.6 到 JDK1.8,字符串常量池从永久代移到堆内存,对于 intern()方法,也产生了一定的变化。

「假设现在有字符串对象 s(这个对象 s 是处于堆中的),它的字符串的内容是"aa"(即字面量为"aa"),并且假设字符创常量池中也不存在字面量"aa"」 。那么在 JDK1.6 中,当调用 s.intern()方法时,由于字符串常量池中不存在"aa&#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值