彻底理解 String.intern

读者可先参考:
深入解析String#intern
Java字符串常量池jdk1.8
《深入理解java虚拟机》String.intern()探究
Java常量池理解与总结
Java中的常量池(字符串常量池、class常量池和运行时常量池)
通过反编译深入理解Java String及intern

然后可对 String.intern 有一个大体地认识。
本篇中的 Java 例子使用的是 jdk1.8。

Java 中的常量池分静态常量池和运行时常量池。

静态常量池

编译后的 *.class 文件中除了有类、方法等描述信息以外,还有常量池,主要存放两大类常量:字面量(Literal)和符合引用量(Symbolic References)。字面量相当于 Java 层面的常量的概念,如文本字符串(数字)字面量,声明为 final 类型的常量等。

符号引用属于编译原理中的概念,包含类、方法的信息:

  • 类和接口的全限定名
  • 字段名称和描述符
  • 方法名称和描述符
运行时常量池

JVM 在完成类加载以后,将类、方法等信息保存到元空间(jdk1.8 以前是方法区),会将 class 文件中的常量池存到堆中(jdk1.7 以前是存在方法区的运行时常量池中)。

运行时常量池相对于 class 文件常量池另外一个特性是具备动态性,并非预置入 class 文件中常量池的内容才能进入堆中的运行时常量池,运行期间也可以将新的常量放入池中,比如使用 String 类的 intern() 方法。

Java 示例

code1:

public class StringInternDemo {
    public static void main(String[] args) {
        test1();
    }

    public static void test1() {
        String b = new String("flower");
        String c = new StringBuilder().append("flow").append("er").toString();
        System.out.println(c.intern() == c);    // false
    }
}

code2:

public class StringInternDemo0 {
    public static void main(String[] args) {
        test2();
    }

    public static void test2() {
        String a = new String("flower" + "brown");
        String c = new StringBuilder().append("flow").append("er").toString();
        System.out.println(c.intern() == c);     // true
    }
}

为什么 code1 输出是 false,而 code2 是true 呢? code1 和 code2 的区别不大啊。前面说过 .class 文件中有常量池,在完成类加载以后会将类中的常量池保存到堆中,下面来看看 code1 和 code2 的字节码文件中的常量池。
code1:
在这里插入图片描述
code2:
在这里插入图片描述
从 code1 和 code2 的 class 常量池中存在 flower 和 flowerbrown。

来看图示:
code1:
在这里插入图片描述
在类加载完以后,堆中的常量池就存在 flower 了(网上很多文章说编译期就确定了),String b = new String("flower");会创建两个对象,堆中创建一个,常量池中有一个(如果常量池中存在这个对象了,就不进行创建了)。明显,c.intern 返回的对象的地址和 c 本身所指向的地址是不一样的,输出 false。

code2:
在这里插入图片描述
String a = new String("flower" + "brown");会在类加载后在常量池中确定 flowerbrown,此时常量池中是没有 flower 和 brown 的,所以这行代码 也只是创建两个对象,String:字符串常量池 这篇文章说会创建 4 个对象(flower、brown、flowerbrown、new String())其实是不对的。

c.intern() 发现常量池中并不存在 flower,则会在常量池中进行创建,但只是保存 flower 在堆中的引用,这个引用和 c 都是指向相同的地址,所以这里输出是 true。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值