Java如何存储字符串以及子字符串如何在内部工作?

时间:2013-01-07 10:00:03

标签: java string substring

class StringTesting {
    public static void main(String args[])
    {
        String str = "abcd";
        String str1 = new String("abcd");
        String str2 = str.substring(0,2);
        String str3 = str.substring(0,2);
        String str4 = str.substring(0,str.length());
        String str5 = str1.substring(0,2);
        String str6 = str1.substring(0,2);
        String str7 = str1.substring(0,str1.length());

        System.out.println(str2 == str3);
        System.out.println(str == str4);
        System.out.println(str5 == str6);
        System.out.println(str1 == str7);
    }
}

以下是我在java 1.6.0_27上获得的输出:

false
true
false
true

有人可以解释输出。我知道Java区分存储在堆中的String和存储在String“common pool”中的String(可以是interned)。在内部,他们的表现如何不同。它是如何改变子串算法的。 请在适当的地方引用书籍/文章/博客等。

2 个答案:

答案 0 :(得分:21)

见评论:

    String str = "abcd";  // new String LITERAL which is interned in the pool
    String str1 = new String("abcd"); // new String, not interned: str1 != str
    String str2 = str.substring(0,2); // new String which is a view on str
    String str3 = str.substring(0,2); // same: str3 != str2
    String str7 = str1.substring(0,str1.length()); // special case: str1 is returned

注意:

  • 从Java 7u6开始,substring返回一个新字符串而不是原始字符串上的视图(但这对该示例没有影响)
  • 致电str1.substring(0,str1.length());时的特殊情况 - 请参阅代码:

    public String substring(int beginIndex, int endIndex) {
        //some exception checking then
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }
    

修改

  

什么是观点?

在Java 7u6之前,String基本上是char[],它包含带有偏移量和计数的字符串的字符(即字符串由count字符组成,从{{1}开始位于offset)。

调用substring时,会创建一个具有相同char[]但不同偏移量/计数的新字符串,以有效地在原始字符串上创建视图。 (如上所述,当count = length和offset = 0时除外)。

从java 7u6开始,每次都会创建一个新的char[],因为字符串类中不再有char[]count字段。

  

公共池的存储位置在哪里?

这是特定于实现的。在最近的版本中,池的位置实际上已移动。在更新的版本中,它存储在堆上。

  

游泳池是如何管理的?

主要特征:

  • 字符串文字存储在池中
  • Interned字符串存储在池中(offset
  • 当字符串new String("abc").intern();被插入时(因为它是文字或因为S被调用),如果存在intern(),JVM将返回对池中字符串的引用。 1}}到equals(因此S应始终返回true)。
  • 池中的字符串可以被垃圾收集(这意味着如果某个阶段的字符串变满,可能会从池中删除该字符串)

答案 1 :(得分:2)

String是不可变的对象。

String#subString - 创建一个新的String。 Source

在代码中它是[open jdk 6] -

 public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > value.length) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    int subLen = endIndex - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return ((beginIndex == 0) && (endIndex == value.length)) ? this
            : new String(value, beginIndex, subLen);
}