在阅览 周志明《深入了解Java虚拟机时》,遇到了一个经典的事例,了解时花费了较多时刻,这儿分享一下自己的考虑。

事例

public void test01() {
    String str1=new StringBuilder("计算机").append("软件").toString();
    System.out.println(str1.intern()==str1);//true
    String str2=new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern()==str2);//false
}

预备常识

在JDK 7以及以上的版别中,因为字符串常量池和String目标都处在 堆 上,因而字符串常量池贮存的是对堆中字符串目标的引证。

intern()办法的作用:假如字符串是第一次呈现,该办法会将字符串参加字符串常量池中;假如不是第一次呈现,那么会将字符串在字符串常量池中的引证回来。

原因解说

那么为什么会呈现上面的现象呢?

需求留意的是,字符串在Java中也是一类特别的目标,只不过因为它常运用作了特别的优化(如字符串常量池)。

在第一个事例中,因为”计算机软件”是第一次呈现,所以intern()办法回来的便是str1的地址。

在第二个事例中,因为”java”先前呈现过,因而intern()办法回来的是先前呈现的”java”字符串地址(在sun.misc.Version中被加载)

图示如下:

关于String.intern()返回测试的详细解释以及思考

部分考虑

  • 在阅览书本时,有过疑问为什么要运用StringBuilder而不直接运用String?
  • 为什么特意append?
public void test02() {
    String str1=new StringBuilder("计算机软件").toString();
    System.out.println(str1.intern()==str1);//false
    String str2=new StringBuilder("java").toString();
    System.out.println(str2.intern()==str2);//false
}
public void test03() {
    String str1="计算机"+"软件";
    System.out.println(str1.intern()==str1);//true
    String str2="ja"+"va";
    System.out.println(str2.intern()==str2);//true
}

能够看出,这儿是运行结果和原事例中是不同的。

要了解这个问题,需求先知道

  • 在任何地方呈现的被””包裹的字符串都会被参加常量池
  • JVM会将形如”ja”+”va”的字符串自动优化为”java”再参加字符串常量池
  • StringBuilder在运用toString()办法时会产生新的字符串目标,不会从字符串常量池中获取,而且不会将生成的字符串参加字符串常量池 参考博客

1、运用StringBuider以及append()的原因:

而原事例test01()中,经过StringBuilder的append()办法奇妙地避开了JVM会将形如”ja”+”va”的字符串自动优化为”java”再参加字符串常量池的特性,因而能够在之后调用intern()办法将字符串参加常量池。以Str1为例,会将”计算机”和”软件”别离参加字符串常量池,而不会将”计算机软件”参加常量池。

2、test02()中都为false的原因:

因为特性在任何地方呈现的字符串都会被参加常量池,在test02()中先创建了String目标”计算机软件”,直接将”计算机软件”参加到字符串常量池中了,再将”计算机软件”转为StringBuild,最终再次经过toString()转为str1,这儿的str1为新的字符串目标。而str1.intern()调用是回来的是”计算机软件”的地址,而不是str1的地址

3、test03()中都为true的原因:

直接运用String时,java虚拟时机自动优化,将”ja”和”va”自动合并成”java”,而且因为在字符串常量池中存在,会直接回来字符串常量池中的引证。值得指出的是,这儿的str1.intern()==str1的原因和原事例中是不同的,这儿的str1在创建时就被参加到字符串常量池,因而str1.intern()在这儿并不会执即将str1参加常量池的行为,而是直接回来字符串常量池中队str1的引证。

因而StringBuilder和append()办法缺一不可

因为笔者也刚接触JVM,写的不好望指正