Java:String intern()和StringPool的工作原理是什么?

时间:2015-12-26 18:59:50

标签: java string

据Javadoc所说String.intern()

  

当调用intern方法时,如果池已经包含一个等于此String对象的字符串(由equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。

关于这个问题我几乎没有问题。

  1. 当创建一个新的String对象(不使用字符串文字但使用new()运算符)时,如: String str = new String("Test");
  2. 问题:我知道将在堆中创建一个新对象。但是它会在对象创建期间将String Test放入字符串池吗?如果是,那么为什么不直接为字符串池返回引用。如果不是,为什么不直接将字符串放在池中,因为现在StringPool已经移出PermGen并且处于常规堆空间中(即除了堆空间限制之外没有空间约束)。有一些帖子说明一旦创建了对象就将String插入到池中,而有些帖子也与此相矛盾。

    1. 一旦我们在String对象上调用String.intern()(因为文字已被实体化),分配给该对象的空间会发生什么?它是在同一时间回收还是等待下一个GC循环?

    2. 在SO上接受another question的回答,声明当你需要速度时应该使用String实习生,因为你可以通过引用比较字符串(==比等于更快)。

    3. 问题:我知道在使用String.intern()时,它会返回对StringPool中已存在的字符串的引用。但这需要在StringPool上进行全扫描查找,这本身​​就是一项昂贵的操作。那么在字符串比较期间达到的速度是否合理?如果是这样,为什么?

      我查看了以下来源:

1 个答案:

答案 0 :(得分:0)

  1. 所有字符串文字都在编译时间内实现。使用带有字符串的单个参数构造函数的字符串文字有点滥用该构造函数,因此您可能会得到其中的两个(但可能有一个特殊的编译器案例,我不能说当然)。从java 8开始,构造函数(对于openjdk)的实现是这样的:
  2. public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    

    所以这方面没有特别的待遇。如果您知道文字不使用此构造函数。

    1. 我不认为Strings有任何特殊的GC语义。一旦它无法到达并被GC认为是值得的任何其他对象,它将被收集。

    2. 不要使用==来比较字符串,字符串的默认equals方法的第一步就是这样做。如果这是你占主导地位的情况(你知道你大部分时间都在使用实习字符串),你只需支付一个很小的方法调用的开销,你通过做类似的事情来增加未来错误的可能性太大了收益微不足道的风险。