String常量池机制案例

StringTable

例1:

String s1 = "abc";
String s2 = "a"+"b"+"c";  // 在编译时会转换为 String s2="abc";
System.out.println(s1==s2) // true

例2:

String s1 = "abc";
String s2 = "def";

String s3 = "abc"+"def";
String s4 = "abcdef";

String s5 = s1+"def";
String s6 = s1+s2;

// 拼接符号前后出现变量时,相当于new String(),内容为拼接的结果
System.out.println(s4==s5); // false
System.out.println(s4==s5); // false

例3:下列语句会生成几个对象?

String s = new String("ab");
  • 上述代码会生成两个对象
  • 一个是由new在堆上生成的对象
  • 另一个是由字节码 ldc 在String常量池中生成的对象
    例4:下列语句会生成几个对象
String s = new String("a") + new String("b");
  • 上述代码会生成6个对象
  • new String(“a”)和new String(“b”)会分别生成两个对象,合计4个对象
  • String拼接生成一个StringBuilder对象
  • StringBuilder.toString()会在堆中返回拼接完成后的String对象,此时不会调用 ldc 在常量池中生成该String对象
个人想法:
代码中的明文字符串会自动放入String常量池,因此toString()返回的字符串没有提前放入常量池。而上述两端代码中存在明文的String对象,可能在代码编译时或其他代码运行前的阶段已经放入常量池,之后new关键字又在堆中生成另一个String对象

例5:

public class Main {  
    public static void main(String[] args){  
        String s1 = new String("1");  
        s1.intern();  
        String s2 = "1";  
        System.out.println(s1==s2); // jdk6:false  jdk7/8:false  
  
        String s3 = new String("a")+new String("b");  
        s3.intern();  
        String s4 = "ab";  
        System.out.println(s3==s4); // jdk6:false  jdk7/8:true  
    }  
}
  • 造成上面情况的原因在于jdk6和jdk7/8中intern()的执行机制不同
  • jdk6:在String常量池中生成调用该方法的String对象副本
  • jdk7/8:在String常量池中添加调用该方法的String对象的引用。若常量池中本来就存在该String对象,则返回原本常量池里的String对象的引用。后面使用该对象的明文字面量时,仍然是根据地址取到最初的实例对象

参考b站尚硅谷宋红康jvm课程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值