最近在看虚拟机,了解到了有关intern的知识,感觉理解起来有点困难,于是乎就直接动手敲敲代码。
以下是案例(注意:测试环境是jdk 1.7以上,1.6以下结果因为永久代的影响又是另一个!)
案例1:
String str1 = new String("计算机") + new String("软件");
System.out.println(str1 == str1.intern());
System.out.println(str1 == "计算机软件");
输出结果:true true
案例2:
String str1 = new String("计算机") + new String("软件");
System.out.println(str1 == "计算机软件");
System.out.println(str1 == str1.intern());
输出结果:false false
Q:为什么两句输出语句交换了位置就输出了,不同的结果呢?
A:
首先肯定不是因为println交换位置而导致的,实际上是因为intern的执行顺序的不同影响的结果。
我们逐句分析,首先将new了两个String类型赋值给str1对象。
此时常量池里面存在了“计算机”,“软件”这两个字符串
假如先执行案例2:
我们可以看到 str1的内存地址是@498指向一个char数组,str1与“计算机软件”的地址比较的时候肯定是不相同的,所以第一句返回的是false。
而因为比较的时候“计算机软件”这个字符串已经在字符串常量池中被创建,所以intern方法(jdk1.7中会先查询字符串常量池,若没有又会到堆中再去查询并存储堆的引用,然后返回。如果字符常量池中已经有该字符则无意义。),所以
str1与str1.intern()做比较就等于str1与“计算机软件”做比较。所以返回的也是false。
假如先执行案例1:
执行intern方法,因为“计算机软件”是第一次出现,所以常量池中并没有这个字符串,所以会到堆中查询,并储存堆的引用,因为str1对象就是指向堆中储存“计算机软件”的对象,所以两者地址一样返回的是true,而同时字符串也会被复制到字符串常量池中,且引用为堆中的那个对象,所以当str1与“计算机软件”做比较时,返回的结果也是true。
为了验证intern在字符串并非第一次出现时是无意义的,我写了以下方法测试:
String str1 = new String("计算机") + new String("软件");
System.out.println(str1 == str1.intern());
System.out.println(str1 == "计算机软件");
String str2 = new String("计算机") + new String("软件");
str2.intern();
System.out.println(str2 == "计算机软件");
System.out.println(str1 == "计算机软件");
输出结果为
true
true
false
true
如果我的理解有错,麻烦各位大牛一定要在评论区指正,谢谢~