String 中 intern 方法的理解

本博文讲解内容均基于hotspot虚拟机

intern用于将字符串存入字符串常量池中,但在不同的JDK版本中有不同之处:


JDK 6中,将调用该方法的字符串对象S尝试放入字符串常量池中(JDK 6字符串常量池在永久代中)

  • 如果字符串常量池中已经存在S内容相同(equals 判断为true)的字符串对象,则不会放入,返回已存在的字符串对象的地址
  • 如果字符串常量池中不存在S内容相同的字符串对象,则会将S复制一份存入字符串常量池中,并返回其地址

从JDK 7起中,将调用该方法的字符串对象S尝试放入字符串常量池中(JDK 7起,字符串常量池在中)

  • 如果字符串常量池中已经存在S内容相同(equals 判断为true)的字符串对象,则不会放入,返回已存在的字符串对象的地址
  • 如果字符串常量池中不存在S内容相同的字符串对象,则会将S引用地址复制一份存入字符串常量池中,并返回这个引用地址

    public static void main(String[] args) {
        String s1 = new String("a") + new String("a");
        s1.intern();
        String s2 = "aa";

        System.out.println(s1 == s2); //    jdk1.6:false   jdk7/8 : true
    }

在JDK 7 起:

  • 1、在字符串常量池中创建字符串对象 “a”
  • 2、在堆中创建了的两个字符串对象 “a”(使用字符串常量池中的"a"作为String构造器参数创建对象),底层调用StringBuilder实现这两个字符串的拼接,返回一个值为"aa"的字符串对象(此对象在堆中),将地址给 s1
    注意:此步骤并不会再字符串常量池中生成字符串"aa"
    String 中 intern 方法的理解_第1张图片
  • 3、s1 调用 intern 方法,发现字符串常量池中已有没有值为 “aa” 的字符串对象,于是在字符串常量池中将 s1 指向的字符串对象的地址复制一份放入字符串常量池中
  • 4、String s2 = “aa” ,字面量直接赋值去字符串常量池中找。发现字符串常量池中有指向"aa"的引用,返回这个引用,s2接收

String 中 intern 方法的理解_第2张图片


上述例子在jdk6中内存结构:
String 中 intern 方法的理解_第3张图片

你可能感兴趣的:(java)