14

重複の可能性:
Javaの「newString(…)」という表現の目的は何ですか?

不変クラスオブジェクトのコピーがオリジナルと等しい場合String、Javaのクラスにコピーコンストラクタがあるのはなぜですか?それは間違いですか、それともこの実装の背後に理由がありますか?Javaドキュメントでは、次のように指定されています。

/**
 * Initializes a newly created {@code String} object so that it represents
 * the same sequence of characters as the argument; in other words, the
 * newly created string is a copy of the argument string. Unless an
 * explicit copy of {@code original} is needed, use of this constructor is
 * unnecessary since Strings are immutable.
 *
 * @param  original
 *         A {@code String}
 */
 public String(String original) {
 ....
 ....}
4

1 に答える 1

11

文字列をコピーする主な理由は、「手荷物をトリミングする」ことです。つまり、基になるchar配列を必要なものだけにトリミングします。

substringを呼び出して文字列を作成すると、char配列が新しい文字列インスタンスとソース文字列インスタンスの間で共有される可能性があるため、基になるchar配列は主に大きすぎる可能性があります。オフセットは最初の文字を指し、長さが含まれます。

私が使用する式「手荷物をトリミングする」は、文字列コピーコンストラクターのソースコードから取得されます。

  164       public String(String original) {
  165           int size = original.count;
  166           char[] originalValue = original.value;
  167           char[] v;
  168           if (originalValue.length > size) {
  169               // The array representing the String is bigger than the new
  170               // String itself.  Perhaps this constructor is being called
  171               // in order to trim the baggage, so make a copy of the array.
  172               int off = original.offset;
  173               v = Arrays.copyOfRange(originalValue, off, off+size);
  174           } else {
  175               // The array representing the String is the same
  176               // size as the String, so no point in making a copy.
  177               v = originalValue;
  178           }
  179           this.offset = 0;
  180           this.count = size;
  181           this.value = v;

これは多くの開発者が忘れていることであり、小さな文字列が大きなchar配列のガーバッグを防ぐ可能性があるため重要です。私がすでにこれを指摘したこの関連する質問を参照してください:Javaはガベージコレクションメモリではありません。多くの開発者は、Java設計者が、Cコーダーに馴染みのあるこの古い最適化のトリックを使用するという決定よりも、実際には、良いというよりも害があると考えています。私たちの多くは、それに噛まれて、何が起こったのかを理解するためにSunのソースコードを調べなければならなかったので、それを知っています...

Markoが指摘しているように(以下のコメントを参照)、OpenJDKでは、java 7 Update 6以降substring、char配列を共有しなくなったString(String)ため、コンストラクターは役に立ちません。しかし、それでも高速であり(実際にはさらに高速です)、この変更はすべてのVM(およびおそらくすべての顧客ではない)に伝達されていなかったためnew String(substring)、古い動作がそれを正当化するときに使用するこのベストプラクティスを維持することをお勧めします。

于 2012-12-10T15:05:04.407 に答える