9
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は、ヒープに格納された文字列と文字列「共通プール」(インターン可能)に格納された文字列を区別することを知っています。内部的には、それらの表現はどのように異なりますか。部分文字列アルゴリズムをどのように変更しますか。本/記事/ブログなどを適宜引用してください。

4

2 に答える 2

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

ノート:

  • Java 7u6以降、部分文字列は元の文字列のビューではなく新しい文字列を返します(ただし、その例では違いはありません)
  • あなたが呼び出すときの特別なケース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 までは、文字列は基本的にchar[]、オフセットとカウントを含む文字列の文字を含む です (つまり、文字列はの位置countから始まる文字で構成されます)。offsetchar[]

substring を呼び出すと、同じchar[]であるが異なるオフセット/カウントで新しい文字列が作成され、元の文字列のビューが効果的に作成されます。(上で説明したように、count = length および offset = 0 の場合を除きます)。

Java 7u6 以降、文字列クラスにはそれ以上またはフィールドchar[]がないため、毎回 new が作成されます。countoffset

共通プールは正確にはどこに保存されていますか?

これは実装固有です。プールの場所は、最近のバージョンで実際に移動しました。最近のバージョンでは、ヒープに格納されます。

プールはどのように管理されていますか?

主な特徴:

  • 文字列リテラルはプールに格納されます
  • インターンされた文字列はプールに格納されます ( new String("abc").intern();)
  • 文字列Sが (リテラルである、または呼び出されたために) インターンされている場合intern()、JVM はプール内の文字列への参照をequals返しますS(したがって、"abc" == "abc"常に true を返す必要があります)。
  • プール内の文字列はガベージ コレクションが可能です (つまり、インターンされた文字列は、プールがいっぱいになると、ある段階でプールから削除される可能性があります)。
于 2013-01-07T10:02:36.473 に答える
2

String不変オブジェクトです。

String#subString- 新しい String を作成します。ソース

コードでは [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);
}
于 2013-01-07T10:02:05.467 に答える