0

このテストを見てください

    String s1 = "1234";
    String s2 = "123";
    Field field = String.class.getDeclaredField("value");
    field.setAccessible(true);
    char[] value1 = (char[]) field.get(s1);
    char[] value2 = (char[]) field.get(s2);
    System.out.println(value1 == value2);

これは出力さfalseれ、JVMがs1とs2に対して2つの異なるchar配列を保持していることを意味します。s1とs2が同じchar配列を共有できない理由を誰かが説明できますか?java.lang.Stringはコンテンツ共有用に設計されたようですね。

注:すべてのJVMについてはわかりません。これは、OracleのJava HotSpot(TM)クライアントVM 22.1-b02(JRE 1.7)です。

アップデート

一方、部分的な共有がまれな場合(String.substringによって作成された文字列のみのようです)、なぜすべての文字列int countint offsetフィールドが必要なのですか?無駄な8バイトです。これはサイズだけでなく、作成速度でもあります。オブジェクトが大きいほど、初期化が長くなります。これがテストです

    long t0 = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        new String("xxxxxxxxxxxxx");
    }
    System.out.println(System.currentTimeMillis() - t0);

約200msかかります。このクラスを使用する場合

class String2 {
    char[] value;
    String2(String2 s) {
        value = s.value;
    }
}

約140ミリ秒かかります。

4

3 に答える 3

5

s1とs2が同じchar配列を共有できない理由を誰かが説明できますか?

おそらく、JVMの起動時間は、部分的な一致がないか文字列プールを調べることによって影響を受けるためですintern

インターンされていない文字列では、場合によってはchar配列を共有できることに注意してください。

String s1 = "1234";
String s2 = s1.substring(0, 3);

...少なくともOpenJDK6を介して。どうやら、OpenJDK7ではもう共有していません( ここで教えてくれたMarko Topolnikに感謝します)

そして興味深いことに、インターンの場合、SunのJVM1.6はそれらを分離します。

String s1 = "1234";
String s2 = s1.substring(0, 3);
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] value1 = (char[]) field.get(s1);
char[] value2 = (char[]) field.get(s2);
System.out.println(value1 == value2);
s2 = s2.intern();
value2 = (char[]) field.get(s2);
System.out.println(value1 == value2);

私は得る:

true
false

他の文字列のサブセットである文字列をインターンプールに含めるのは好きではないと思います。

于 2012-12-10T15:39:33.593 に答える
4

s1とs2が同じchar配列を共有できない理由を誰かが説明できますか?

"1234"はと同じ文字シーケンスではないためです"123"

于 2012-12-10T15:38:35.667 に答える
0

私の考えでは、JVMが文字列をインターンする際にその長さにならないのは、それだけの価値がないからです。

提案するようにスペースの使用を最小限に抑えるインターンの単純な実装では、JVMの存続期間中にインターンされる一意の文字列データの文字数がO(N^2)パフォーマンスになります。N(わかりました、それはそれより少し複雑です...しかしそれは高価です。)

O(N^2)問題を回避しようとした実装は、通常、文字配列を共有することによって節約されるよりも多くのスペースを使用して問題を回避することになります。

文字列の実装(インターンを含む)は、実際のアプリケーションの範囲で平均したときに最高のパフォーマンスを提供するために、競合する懸念のバランスをとる実用的な実装です。

于 2012-12-16T07:43:42.020 に答える