1. ホーム
  2. java

Javaで「new String(...)」という表現は何のためにあるのでしょうか?

2023-11-21 14:17:56

質問

オンラインのコードサンプルを見ていると、new 演算子を用いて String 定数を String オブジェクトに代入しているのを見かけることがあります。

たとえば

String s;
...
s = new String("Hello World");

これは、もちろん、比較すると

s = "Hello World";

私はこの構文に精通していないので、目的または効果が何であるか全くわかりません。 String 定数は通常、定数プールに格納され、その後、JVM が String 定数を処理するために持っている任意の表現に格納されるので、何かがヒープ上に割り当てられることさえあるでしょうか?

どのように解決するのですか?

あなたが を考える と思っているところです。 new String(String) のように、内部の文字配列の別個のコピーを強制することです。

small=new String(huge.substring(10,20))

しかし、この動作は残念ながら文書化されておらず、実装に依存しています。

私は、大きなファイル (いくつかは最大 20 MiB) を文字列に読み込んで、事後的にそれを行に切り分けたときに、これによって火傷を負いました。 私は、ファイル全体からなる char[] を参照する行のすべての文字列を終了しました。 残念ながら、これでは意図せず、ファイルを処理するよりも長い時間、私が保持するいくつかの行のために配列全体への参照を保持することになります - 私は強制的に new String() を使用して回避することを余儀なくされました。2 万個のファイルを非常に迅速に処理すると膨大な量の RAM が消費されるためです。

実装に依存しない唯一の方法は

small=new String(huge.substring(10,20).toCharArray());

これは残念ながら、配列を2回コピーする必要があります。 toCharArray() に対して一度、そして String コンストラクタで一度です。

既存の文字列をコピーして新しい文字列を取得する方法を文書化する必要があります。 String(String) のドキュメントをより明確にするために改善する必要があります(そこに含意はありますが、かなり曖昧で解釈の余地があります)。

ドキュメントに記載されていないことを仮定してしまうという落とし穴

続々と寄せられるコメントに応えて、Apache Harmony の実装である new String() がどうだったかを観察してください。

public String(String string) {
    value = string.value;
    offset = string.offset;
    count = string.count;
}

その通り、基礎となる配列のコピーはありません。 それでも、(Java 7の)Stringのドキュメントに準拠しているということです。

新しく作成されたStringオブジェクトを初期化し、引数と同じ文字列を表します。オリジナルの明示的なコピーが必要でない限り、Stringは不変なので、このコンストラクタの使用は不要です。

重要なのは、"引数のコピーであることです。 文字列 引数文字列とその文字列をサポートする基礎となる文字配列のコピー"とは書いてありません。

にプログラムすることに注意してください。 ドキュメント でなく 一つ 実装 .