String.intern()是一个本地(native)方法,它的作用是如果字符串常量池中已经包含一个等于此String对象的字符串,则返回该字符串的String对象的引用,否则会创建一个String对象添加到字符串常量池中,并且返回此对象的引用,在jdk6或更早之前的虚拟机中常量池都是分配到永久代中,我们可以通过-xx:PermSize和-xx:MaxPermSize限制永久代的大小,即可间接限制其常量池的容量,在jdk8中完全使用元空间来代替永久代。
示例代码:
public static void main(String[] args) { String str=new StringBuilder("58").append("tongcheng").toString(); System.out.println(str); System.out.println(str.intern()); System.out.println(str==str.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()); String s="java"; System.out.println(s==str2.intern()); }
执行结果:
58tongcheng 58tongcheng true java java false true
为什么58tongcheng是true而 java的str2==str2.intern()是false?
因为有一个初始化的java字符串(jdk自带的)在加载sum.misc.Version这个类的时候进入常量池
sun.misc.Version类会在JDK类库的初始化过程中被加载并初始化,而在初始化时它需要对静态常量字段根据指定的常量值(ConstantValue)做默认初始化,此时被 sun.misc.Version.launcher静态常量字段所引用的"java"字符串字面量就被intern到HotSpot VM的字符串常量池——StringTable里了。
所以 new StringBuilder("ja").append("va").toString();时是new了一个,打印第一行str2的时候是这个new的字符串,第二句str2.intern()是jdk自带的这个launcher_name变量的java值,所以打印出false.不是同一个String对象
String s="java"; System.out.println(s==str2.intern());为true,s就是原来的jdk加载的java字符串
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)