为什么像concat这样的String方法会创建一个新的String对象?

时间:2017-03-12 09:50:54

标签: java string

为什么像concat()之类的方法返回一个新的String对象而不是从String池返回一个对象?我发现有一个名为intern()的方法,它从String池返回对象。我仍然不明白为什么像concat()这样的方法在返回一个新的String时不使用这个方法。

String a = "test";
String b = "tes".concat("t"); //but not "tes".concat("t").intern();


public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true); // return new String(buf, true).intern();
}

1 个答案:

答案 0 :(得分:2)

您应该注意,在String上调用intern()不会阻止创建原始String。即大部分短期费用已经支付,实习期间可能会使大多数用例更糟糕。

String.intern()是为String常量而设计的,这些常量是长寿命的。他们是Perm Gen的一部分(直到Java 6)并且相对很少被清理。字符串实习池的另一个限制是,如果您在其中加载了许多字符串,则桶大小不会调整大小并且您可能会对性能产生重大影响。即它不是为此设计的。

在G1收集器中,你有一个-XX:+UseStringDeduplication这会减少字符串重复,或者更具体地说是String的基础数组。这不会对实际的String对象进行重复数据删除,因为这可能会产生意想不到的副作用。注意:此重复数据删除仅在GC运行时发生。

  

为什么游泳池会开始消耗大量内存?

记录String对象的数据结构增加了内存,并且更有可能保留内存,因为这些内容往往会在终身空间中结束并需要一个主要的集合来清理。

  

我的意思是所有新创建的String对象都将引用常量池中的对象。

您仍然会创建一个短暂的String。并且您将在池中使用一些空间,因此对于某些用例(实际上大部分都是这样),这会占用更多内存并且更难清理。

  

我认为我们会以这种方式使用更少的内存。

它可以,这就是为什么String重复数据删除是一个更好的选择,因为它只会执行中长期对象。

顺便说一句:明显而不是

String b = "tes".concat("t");

你应该写

String b = "tes" + "t";

因为javac编译器可以组合这些。