一、intern()
方法
运行时常量池是方法区的一部分,在JDK 8的时候,方法区概念的落地实现由永久代变成了元空间
intern()
方法的源代码如下图所示
intern()
方法是一个本地方法调用该方法时,如果字符串常量池中已经存在一个等于此String对象的字符串,就直接从常量池中返回这个字符串对象的引用如果调用该方法的这个字符串对象,目前字符串常量池中还并不存在这个字符串对象,也就是说这个字符串对象是首次出现的,那么就新建并添加这个字符串对象到字符串常量池中,并返回新建的字符串对象的引用
二、字符串常量Java内部加载
public class intern {public static void main(String[] args) {String str1 = new StringBuilder("hello").append("world").toString();System.out.println(str1);System.out.println(str1.intern());System.out.println(str1 == str1.intern());System.out.println();String str2 = new StringBuilder("ja").append("va").toString();System.out.println(str2);System.out.println(str2.intern());System.out.println(str2 == str2.intern());}}
输出结果
StringBuilder
创建的字符串对象是在堆上,调用intern()
方法会把这个字符串对象实例引用放到字符串常量池,并返回这个字符串对象的引用。因此intern()
返回的引用和由StringBuilder
创建的那个字符串实例就是同一个对象
上述代码都是创建了一个字符串对象并调用intern()
方法把这个字符串对象引用放到了字符串常量池中,但是“helloworld”
字符串返回true
,而“java”
字符串却返回的是false
,这说明“java”
这个字符串之前已经创建过,并把引用存放在了字符串常量池中。
实际上这个“java”
字符串,早就在系统进行初始化时,类加载器加载一些必需的类sun.misc.Version
这个类的时候,这个“java”
字符串就已经进入常量池。
所以很显然Version
这个类创建的“java”
字符串对象的引用和StringBuilder
创建“java”
字符串对象的引用并不是同一个