不同JDK版本之间的intern()方法的区别-JDK6 VS JDK6+

 

String s = new Stirng(“a”);

s.intern();

JDK6:当调用intern()方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,将此字符串对象添加到字符串常量池中,并且返回该字符串的引用。

JDK6+:当调用intern()方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,如果该字符串对象已经存在于Java堆中,则将堆中此对象的引用添加到字符串常量池中,并且返回该引用;如果堆中不存在,则在池中创建该字符串并返回其引用。

注:在JDK1.6的时候,字符串常量池是存放在Perm Space中的(Perm Space和堆是相隔而开的),在1.6+的时候,移到了堆内存中

JDK6:返回false false

【注意:String s = new String("a")的时候, “a”会被首先创建,放入字符串常量池中,然后new出的对象放在堆中,在调用intern()的时候,会尝试将字符串对象放入字符串常量池中,但是发现字符串常量池中已经有了,就不能放了,在String s2 = "a"的时候,会先在常量池中寻找有没有对应的字符串,如果有,就直接返回它的引用,详情可见面试题笔记中的==与equal    在String s3 = new String("a") + new String("a"),字符串常量池是不会创建“aa”这个字符串的,因为“”中只有单个a,所以在调用intern()的时候,会尝试将“aa”也就是堆中的那个字符串对象放入常量池中,并返回字符串常量池中“aa”的引用,但是由于常量池中放的相当于是一个对象副本,当返回它的引用时,地址是永久区的,因此不会相等】

JDK6+:返回false true

J

【注意:String s = new String("a")的时候, “a”会被首先创建,放入字符串常量池中,然后new出的对象放在堆中,在调用intern()的时候,会尝试将字符串对象放入字符串常量池中,但是发现字符串常量池中已经有了,就不能放了,在String s2 = "a"的时候,会先在常量池中寻找有没有对应的字符串,如果有,就直接返回它的引用,详情可见面试题笔记中的==与equal    在String s3 = new String("a") + new String("a"),字符串常量池是不会创建“aa”这个字符串的,因为“”中只有单个a,所以在调用intern()的时候,会尝试将“aa”也就是堆中的那个字符串对象的引用放入常量池中,并将该引用返回,由于这两个都是同一个地址引用,于是相等】

再来看第二段代码:

public static void main(String[] args) {
String s = new String("1");
String s2 = "1";
s.intern();
System.out.println(s == s2);

String s3 = new String("1") + new String("1");
String s4 = "11";
s3.intern();
System.out.println(s3 == s4);
}
1
2
3
4
5
6
7
8
9
10
11
打印结果是

jdk6 下false false
jdk7 下false false

第一段代码和第二段代码的改变就是 s3.intern(); 的顺序是放在String s4 = “11”;后了。这样先执行String s4 = “11”;声明 s4 的时候常量池中是不存在“11”对象的,执行完毕后,“11“对象是 s4 声明产生的新对象。然后再执行s3.intern();时,常量池中“11”对象已经存在了,不需要新建任何对象或引用; 因此 s3 和 s4 的引用是不同的。(一个指向常量池,一个指向Java堆)。

第二段代码中的 s 和 s2 代码中,s.intern();,这一句往后放也不会有什么影响了,因为对象池中在执行第一句代码String s = new String(“1”);的时候已经生成“1”对象了。下边的s2声明都是直接从常量池中取地址引用的。 s 和 s2 的引用地址是不会相等的。

小结

从上述的例子代码可以看出 jdk7 版本对 intern 操作和常量池都做了一定的修改。主要包括2点:

将String常量池从Perm区移动到了Java Heap区

String#intern 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。

原文地址:https://www.cnblogs.com/zyy1688/p/10825507.html