文字列をコピーする主な理由は、「手荷物をトリミングする」ことです。つまり、基になる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)
、古い動作がそれを正当化するときに使用するこのベストプラクティスを維持することをお勧めします。