java中String的intern方法简述

148 阅读3分钟

官方解释(基于jdk1.8)

图片.png 翻译过来就是intern方法会返回来自于字符串常量池中的一个字符串引用。如果调用intern的字符串对象与池中的某个字符串对象equels结果为true,那么表示该字符串在池中已经存在,返回池中字符串对象的引用。反之,将调用intern的字符串对象添加到池中,并返回该对象的引用。

字符串常量池的来源

有两种情况: 1.字符串在代码中通过硬编码定义,即“字面量”,如 String s = "abc"; 这里的“abc”就是字面量。"abc"这个字符串会在编译期放在class文件的class常量池中,在运行期,代码执行到String s = "abc";这一步时,放入字符串常量池,如果常量池中存在equels为true的字符串,则返回已存在字符串的引用。 2.某个字符串对象执行intern方法时,如果池中没有equels为true的另一个字符串对象,则将该对象添加到字符串常量池

当字符串不在池中,调用intern方法时

String s1 = new String("a") + new String("a") ; ①
s1.intern(); ②
String s2 = "aa"; ③
System.out.println(s1 == s2); //true 

上述返回true的原因为,①执行时,只有字面量“a”被放入字符串常量池,s1引用的对象是存在于堆内存中的字符串对象,他引用的字符数组为['a','a']。②执行时,因为字符串常量池中没有与"aa".equels为true的字符串,所以会把s1引用的对象添加到字符串常量池,注意,这里不是在池中新建一个对象,而是新建了一个引用,这个引用指向s1,并返回。③执行时,程序读到了"aa"这个字面量,会先判断字符串常量池中有没有与"aa".equels为true的字符串,由于步骤②已经添加成功,所以这里会返回s1的引用,即堆内存的字符数组为['a','a']的对象。

当字符串在池中,调用intern方法时

我们可以将上述代码换一个形式,改一下第一行:

String s1 = new String("aa"); ①
s1.intern(); ②
String s2 = "aa"; ③
System.out.println(s1 == s2); //false

这里为什么又是false了呢,与第一次不同的是,①执行时不但创建了一个堆内存对象,还在字符串常量池中创建了一个"aa"的对象(因为这里"aa"变成了字面量)。②会返回字符串常量池中"aa"对象的引用,③执行时由于①已经在字符串常量池创建了一个"aa",所以s2实际上是指向了字符串常量池中的"aa"。

总结

java字符串常量池机制的目的是为了尽可能重用字符串常量,intern方法提供了一个将运行期非字面量的字符串添加到常量池的渠道,避免创建大量重复的字符串,占用系统空间。