String str1 = new StringBuilder("a").append("b").toString(); System.out.println(str1.intern() == str1); String str2 = new StringBuilder("c").toString(); System.out.println(str2.intern() == str2);
为什么输出结果是:truefalse
光阴似箭催人老,日月如移越少年。
String str1 = new StringBuilder("a").append("b").toString(); //1 System.out.println(str1.intern() == str1); //2 String str2 = new StringBuilder("c").toString(); //3 System.out.println(str2.intern() == str2); //4
java 内存模型中存在一个叫做 String常量池的区域,其中存放着字符串常量。
首先说明一下,在jdk版本小于等于1.6的时候,执行上述代码的结果会是
false false
jdk 版本大于1.6 时,上述代码的执行结果为
true false
造成以上两种不同结果的原因是,jvm对 intern()方法的实现不同。
在jdk1.6及以前,调用intern()
如果常量池中不存在值相等的字符串时,jvm会复制一个字符串到创量池中,并返回常量池中的字符串。
而在jdk1.7及以后,调用intern()
如果常量池中不存在值相等的字符串时,jvm只是在常量池记录当前字符串的引用,并返回当前字符串的引用。
接下来,我们再解释上述代码在jdk1.7及以上jdk中为什么会得到一个true一个false。
true
false
当存在上述代码的类被JVM加载时,字面值常量 a, b, c 就会被加载到 string 常量池中,当执行str1.intern()时,由于常量池中并不存在字符串ab,jvm 会在常量池中记录str1的引用,并返回str1的引用,因此,第2行代码的输出为true。
a
b
c
str1.intern()
ab
str1
str2使用字面值常量 c 构造了一个新的字符串,该字符串的引用和常量池中字面值c字符串的引用不相同,当调用str2.intern()时, 常量池中已经存在了c,jvm直接返回常量池中的引用,该引用不同于重新构造的str2,因此第4行代码的输出为false。
str2
str2.intern()
一个String对象调用intern()方法会先从常量池中找到equals该对象的常量并返回,若找不到就在常量池中增加一个equals该对象的常量,并返回该常量的应用。System.out.println(str1.intern() == str1);输出为true,是因为str1经过append操作后,变成一个常量池中常量的引用。System.out.println(str2.intern() == str2);输出为false,是因为str2是一个变量的引用,不在常量池中。 因此,我们要判断str.intern() == str是false还是true,主要看str是不是常量池中的常量,如果是结果就是true,否则就过就是false。
intern()
equals
System.out.println(str1.intern() == str1);
append
System.out.println(str2.intern() == str2);
str.intern() == str
str
java 内存模型中存在一个叫做 String常量池的区域,其中存放着字符串常量。
首先说明一下,在jdk版本小于等于1.6的时候,执行上述代码的结果会是
jdk 版本大于1.6 时,上述代码的执行结果为
造成以上两种不同结果的原因是,jvm对 intern()方法的实现不同。
在jdk1.6及以前,调用intern()
而在jdk1.7及以后,调用intern()
接下来,我们再解释上述代码在jdk1.7及以上jdk中为什么会得到一个
true
一个false
。当存在上述代码的类被JVM加载时,字面值常量
a
,b
,c
就会被加载到 string 常量池中,当执行str1.intern()
时,由于常量池中并不存在字符串ab
,jvm 会在常量池中记录str1
的引用,并返回str1
的引用,因此,第2行代码的输出为true
。str2
使用字面值常量c
构造了一个新的字符串,该字符串的引用和常量池中字面值c
字符串的引用不相同,当调用str2.intern()
时, 常量池中已经存在了c
,jvm直接返回常量池中的引用,该引用不同于重新构造的str2
,因此第4行代码的输出为false
。一个String对象调用
intern()
方法会先从常量池中找到equals
该对象的常量并返回,若找不到就在常量池中增加一个equals
该对象的常量,并返回该常量的应用。System.out.println(str1.intern() == str1);
输出为true
,是因为str1
经过append
操作后,变成一个常量池中常量的引用。System.out.println(str2.intern() == str2);
输出为false
,是因为str2是一个变量的引用,不在常量池中。因此,我们要判断
str.intern() == str
是false
还是true
,主要看str
是不是常量池中的常量,如果是结果就是true
,否则就过就是false
。