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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14193571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:25:41  来源:igfitidea点击:

How does Java store Strings and how does substring work internally?

javastringsubstring

提问by Bruce

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);
    }
}

Here is the output I get on java 1.6.0_27:

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

false
true
false
true

Can someone please explain the output. I know Java differentiates between String stored in heap and String stored in String "common pool" (which can be interned). Internally, how is their representation different. How does it change the substring algorithm. Kindly cite book/article/blogs etc. wherever appropriate.

有人可以解释一下输出吗?我知道 Java 区分存储在堆中的字符串和存储在字符串“公共池”(可以实习)中的字符串。在内部,它们的表示有何不同。它如何改变子串算法。请在适当的地方引用书籍/文章/博客等。

回答by assylias

See the comments:

看评论:

    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

Notes:

笔记:

  • Since Java 7u6, substring returns a new string instead of a view on the original string (but that does not make a difference for that example)
  • Special case when you call str1.substring(0,str1.length());- see code:

    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 开始, 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);
    }
    

EDIT

编辑

What is a view?

什么是视图?

Until Java 7u6, a String is basically a char[]that contains the characters of the string with an offset and a count (i.e. the string is composed of countcharacters starting from the offsetposition in the char[]).

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

When calling substring, a new string is created with the same char[]but a different offset / count, to effectively create a view on the original string. (Except when count = length and offset = 0 as explained above).

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

Since java 7u6, a new char[]is created every time, because there is no more countor offsetfield in the string class.

从java 7u6开始,char[]每次都创建一个new ,因为string类中没有morecountoffset字段。

Where is the common pool stored exactly?

公共池究竟存储在哪里?

This is implementation specific. The location of the pool has actually moved in recent versions. In more recent versions, it is stored on the heap.

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

How is the pool managed?

游泳池是如何管理的?

Main characteristics:

主要特征:

  • String literals are stored in the pool
  • Interned strings are stored in the pool (new String("abc").intern();)
  • When a string Sis interned (because it is a literal or because intern()is called), the JVM will return a reference to a string in the pool if there is one that is equalsto S(hence "abc" == "abc"should always return true).
  • Strings in the pool can be garbage collected (meaning that an interned string might be removed from the pool at some stage if it becomes full)
  • 字符串文字存储在池中
  • 实习字符串存储在池中 ( new String("abc").intern();)
  • 当一个字符串S被拘留(因为它是文字还是因为intern()被调用),JVM将参考返回一个字符串池中是否有一个是equalsS(因此"abc" == "abc"应该总是返回true)。
  • 池中的字符串可以被垃圾收集(这意味着如果池中的字符串变满,则可能会在某个阶段将其从池中删除)

回答by Subhrajyoti Majumder

Stringis immutable Object.

String是不可变对象。

String#subString- creates a new String . Source

String#subString- 创建一个新的 String 。来源

In code it is [open jdk 6] -

在代码中它是 [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);
}