intern 方法与字符串常量池

intern

对象 A 在执行 intern 时,会检查字符串常量池中是否存在与对象 A 相同的对象 B。

  • 存在。返回对象 B,此时引用的是对象 B。
  • 不存在。将对象 A 加入常量池,并返回对象 A,此时引用的仍是对象 A。

关于字符串字面量。

  • 在第一次出现字符串字面量时,就会直接加入字符串常量池。

  • 对字符串字面量的引用都是来自字符串常量池的对象。

抓住以上关键点,便可轻松破解下面代码的奥秘。

代码

public class InternDemo {
    public static void main(String[] args) {
        String s1 = UUID.fromString("6d86f4d7-9bfc-47c8-897f-a2f5531bf368").toString(); 
        // 此时第一次出现 "6d86f4d7-9bfc-47c8-897f-a2f5531bf368" 简称该串为 A,则 A 直接加入字符串常量池。所以后续 intern 返回的是 A。
        // Java 中所有按照方法返回的除了 intern 外都是新的对象,所以此处 s1 引用的是新对象 B。
        String s2 = "6d86f4d7-9bfc-47c8-897f-a2f5531bf368"; 
        // 此处直接引用字符串常量池的 A。
        System.out.println(s1.intern() == s2); // true
        // s1.intern 返回的是 A,而 s2 引用的也是 A,所以是 true。
        System.out.println(s1.intern() == s1); // false
        // s1.intern 返回的是 A,而 s1 引用的是 B,所以是 false。

        String s3 = UUID.randomUUID().toString(); 
        // s3 引用的串必然是不存在常量池中的串,该串称之为 C
        System.out.println(s3 == s3.intern()); //true
        // s3 调用 intern 时,字符串常量池中没有与之相同的串,所以会将 C 加入字符串常量池,返回对象 C。
        // 而 s3 也是对 C 的引用。两者引用相同所以是 true。
        
        String s4 = new String("aaa"); 
        // 此时第一次出现 "aaa" 简称该串 D,则 D 直接加入字符串常量池,后续 intern 返回的是 D。但此处 s4 引用的是新对象 E。
        System.out.println(s4.intern() == s4); //false
        // s4.intern 返回的是 D,而 s4 引用的是 E,所以是false。
        
        String s5 = "abb"; 
        // 此时第一次出现 "abb" 简称该串 F,则 F 直接加入字符串常量池,后续 intern 返回的是 F。
        // 对字面量的引用直接来自字符串常量池,所以 s5 的也是对 F 的引用。
        String s6 = s5.intern(); 
        // 此时 s6 引用的是 s5.intern 返回的 F 
        System.out.println(s6 == s5); // true
        // s5 与 s6 均引用 F,所以为 true
        
        String s7 = new StringBuilder("123").append("2").toString();
        // 第一出现 "123" 和 "2",这两个串加入字符串常量池。
        // 但使用 toString 后的 "1232" G 并没有加入字符串常量池,所以 s7 引用的 G,不会被后续通过字面量以及 intern 再次引用。
        String s8 = "123" + "2"; // 会被优化成 "1232",称该串为 H,H 加入字符串常量池,后续相同的串调用 intern 会返回 H
        System.out.println(s7.intern() == s7); // false
        // s7 调用 intern 时会在字符串常量池中匹配到与 G 长的一样的 H,所以返回字符串常量池中的 H。而 s7 引用的是 G,所以为 false
        // 而当 String s8 = "123" + "2"; 注释掉后。
        // 调用 intern 时无法在字符串常量池中找到相同的 H,所以就会将 G 加入字符串常量池。
        // 而此时 s7.intern 与 s7 都是引用自 G,所以会变成 true。
    }
}

读者可自行检验。

参考资料

JVM Stringtable 与 SymbolTable 与字符串 Intern 原理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值