3

String#substringメソッドの実装を見てみると:

new String(offset + beginIndex, endIndex - beginIndex, value);

同じ元のコンテンツ(パラメータchar [] value )で新しい文字列が作成されていることがわかります。

したがって、回避策は new String(toto.substring(...))、元のchar []値への参照を削除し、それをGCの対象にすることです(参照がこれ以上存在しない場合)。

この実装を説明する特別な理由があるかどうか知りたいです。メソッドが新しい短い文字列を自分で作成しないのはなぜですか?また、代わりに完全な元の値を保持するのはなぜですか?

他の関連する質問は:new String(...)部分文字列を扱うときに常に使用する必要がありますか?

4

3 に答える 3

2

String不変クラスから

も参照してください

于 2012-06-20T09:14:06.637 に答える
2

この実装を説明する特別な理由があるかどうか知りたいです。メソッドが新しい短い文字列を自分で作成しないのはなぜですか?また、代わりに完全な元の値を保持するのはなぜですか?

ほとんどのユースケースでは、substring()この方法で作業する方が速いためです。少なくとも、それはSun/Oracleの経験的測定が示したであろうものです。これを行うことにより、実装はバッキング配列の割り当てと配列への文字のコピーを回避します。

これは、メモリリークの問題を回避するために文字列をコピーする必要がある場合にのみ、最適化されません。ほとんどの場合、サブストリングは比較的短時間でガベージになり、メモリの長期的なリークはありません。


仮に、Java設計者はsubstring、現在のように動作するバージョンと、独自のバッキング配列を持つ文字列を作成するバージョンの2つのバージョンを提供できたはずです。しかし、それは開発者がどのバージョンを使用するかを考える脳サイクルを無駄にすることを奨励します。そして、サブストリングに基づいて構築されるユーティリティメソッドの問題があります...たとえばPattern/Matcherクラスのように。ですから、彼らがそうしなかったのは良いことだと思います。

于 2012-06-20T09:20:09.400 に答える
1

この実装の理由は効率です。元の文字列と同じものを指すことによりchar[]、データをコピーする必要がありません。

ただし、すでに自分自身をほのめかしているように、これには欠点があります。元の文字列が長く、その一部を取得したいだけで、その後元の文字列が不要になった場合でも、完全な元の配列が参照され、ガベージコレクションを行うことはできません。あなたはすでにそれを避ける方法を知っています-してくださいnew String(original.substring(...))

new String(...)部分文字列を扱うときは常に使用する必要がありますか?

いいえ、常にではありません。問題が発生する可能性があることがわかっている場合のみ。多くの場合、char[]データをコピーする代わりにオリジナルを参照する方が効率的です。

于 2012-06-20T09:22:17.417 に答える