当前位置 博文首页 > 大叶子不小的博客:记录String中intern()方法的学习与理解

    大叶子不小的博客:记录String中intern()方法的学习与理解

    作者:[db:作者] 时间:2021-08-02 12:35

    由于jdk1.7中将字符串常量池改为存放在堆中,因此intern()方法的实现原理相对以前的版本也有所改变。

    我们根据jdk的版本来进行一些分析:

    jdk1.6中字符串常量池存放在永久代中:

    当使用intern()方法时,查询字符串常量池是否存在当前字符串,若不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。

    jdk1.7中字符串常量池存放在堆中:

    当使用intern()方法时,先查询字符串常量池是否存在当前字符串,若字符串常量池中不存在则再从堆中查询,然后存储并返回相关引用;

    若都不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。

    从上面叙述中,可以得出其中的区别:

    jdk1.6中只能查询或创建在字符串常量池;

    jdk1.7中会先查询字符串常量池,若没有又会到堆中再去查询并存储堆的引用,然后返回。

    验证以上观点:

    String s = new String("1") + new String("2");
    System.out.println(s.intern() == s);
    

    jdk1.6中输出结果为 false

    解释:

    s.intern()查询字符串常量池中是否存在“12”后,将“12”复制到字符串常量池中并返回字符串常量池的引用。

    而s存放在在堆中,返回false。

    jdk1.7中输出结果为 true

    解释:

    s.intern()先查询字符串常量池中是否存在“12”后,再从堆中查询“12”是否存在并存储堆中的引用并返回。

    因此s.intern()与s指向的是同一个引用,返回true。

    借用美团技术团队《深入解析String#intern》一文中两段代码与相关图片来进行解释:

    注:图中绿色线条代表 string 对象的内容指向。 黑色线条代表地址指向。

    String s = new String("1");
    s.intern();
    String s2 = "1";
    System.out.println(s == s2);
    
    String s3 = new String("1") + new String("1");
    s3.intern();
    String s4 = "11";
    System.out.println(s3 == s4);
    

    jdk1.6中输出结果为 false false

    解释:

    String s = new String("1"); 在字符串常量池中创建"1"对象,在堆中创建s对象。

    s.intern(); 由于字符串常量池中已经有"1"对象,因此该句并无实际意义。 s2指向字符串常量池中"1"对象。

    因此s指向堆中的引用,s2指向字符串常量池中的引用,返回 false。

    String s3 = new String("1") + new String("1"); 在堆中创建s3对象。

    s3.intern(); 将字符串"11"复制到字符串常量池中。s4指向字符串常量池中"11"对象。

    因此s3指向堆中的引用,s4指向字符串常量池中的引用,返回 false。

    cs