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

Bru*_*uce 9 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在java 1.6.0_27上得到的输出:

false
true
false
true
Run Code Online (Sandbox Code Playgroud)

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

ass*_*ias 22

看评论:

    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
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 从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);
    }
    
    Run Code Online (Sandbox Code Playgroud)

编辑

什么是观点?

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

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

从java 7u6开始,char[]每次都会创建一个new ,因为字符串类中没有更多countoffset字段.

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

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

游泳池是如何管理的?

主要特征:

  • 字符串文字存储在池中
  • Interned字符串存储在池中(new String("abc").intern();)
  • 当一个字符串S被拘留(因为它是文字还是因为intern()被调用),JVM将参考返回一个字符串池中是否有一个是equalsS(因此"abc" == "abc"应该总是返回true).
  • 池中的字符串可以被垃圾收集(这意味着如果池中的字符串变满,可能会在某个阶段从池中删除它)