String API を調べていたところ、突然 String の空のコンストラクターが 1 つ見つかりました。つまり、次を使用して空の String オブジェクトを構築できますString s = new String()
使い道があるのかしら。
もちろん.....
String s = new String();
は、ガベージ コレクションされるヒープ上に非リテラル String オブジェクトを作成します。
一方
String s = "" ;
文字列リテラルを作成します。デフォルトのローダーを介して到達できる場合、これはガベージコレクションされません。
私が尋ねた質問については、以下のこのリンクを参照してください。ご質問とは直接関係ないかもしれませんが、概念をしっかりと理解するのに役立つはずです。
使用が制限されているように見える空の文字列を作成します。
String
連結して a を作成し、 eg を使用しない場合StringBuiler
、コードは次のいずれかとして開始できます。
String result = new String();
String result = "";
String result = "first part of string";
// ...
result += "append to the result";
最初の 2 つは同等ではなく、文字列のインターン""
を利用できるため、で初期化することをお勧めします。
小さな例...文字列はガベージコレクションできます
System.out.println(1 + new String() + 2);
それ以外の
System.out.println(1 + "" + 2);
Java の文字列は不変であるため、「インターン」されます。つまり、ロードされたクラスのすべての文字列リテラルがプールに保持されるため、通常、メモリ内には一度に一意の各文字列リテラルのインスタンスが 1 つだけ存在します。これはflyweight パターンのアプリケーションであり、同様のプールが Integer およびその他のプリミティブ ラッパー オブジェクトに対しても保持されます (ただし、限られた数の小さな値に対してのみ)。
このメカニズムにより、文字列リテラル (異なるクラスからのものであっても) の同一性比較は通常可能です (ただしequals
、安全性と一貫性のために文字列を比較するときは常にメソッドを使用する必要があります)。
System.out.println("hello" == "hello"); // true
ここで、デフォルトの文字列コンストラクターを使用すると、空の文字列のインスタンスが取得されますが、JavaDoc に記載されているように、それは新しいインスタンスです。
空の文字シーケンスを表すように、新しく作成された String オブジェクトを初期化します。String は不変であるため、このコンストラクターの使用は不要であることに注意してください。
このような新しいインスタンスは、インターンされた空の文字列とは異なり、次のようになります。
System.out.println(new String() == ""); // false
しかし、私が言ったように、文字列リテラルのみが自動的にインターンされます。つまり、char 配列などから StringBuilders によって手動で作成された文字列はインターンされません。String.intern()メソッドを使用して、そのような文字列を手動でプールに入れることができます。
これは確かに素晴らしいことですが、このコンストラクターが存在する理由についてはまだ答えていません。Java 文字列は単なるchar 配列のスマート ラッパーであり、いくつかの異なる文字列オブジェクトは内部配列を共有できます。
非常に長い文字列を作成した場合 (たとえば、ストリームから読み取ることによって)、このインスタンスは (上記のように) インターンされないため、それを参照した変数が範囲外になった後にガベージ コレクションが行われます。しかし、これを行う場合:
String longString = readVeryLongString();
String shortString = longString.subString(0, 10);
...その後、 newshortString
は から最初の 10 文字をコピーせず、longString
それらを独自の新しい char 配列に入れます。いいえ、最初の 10 文字のみを使用して、元の配列を参照します。
ここで、shortString 変数の寿命が長い場合 (たとえば、静的コンテキストに置かれる場合)、基になる char 配列はガベージ コレクションされません(元のlongString
変数が既にスコープ外になっている場合でも)。これは、Java でメモリ リークを作成する方法の 1 つです。
ここで、デフォルトの文字列コンストラクターが助けになります! 上記のコードを次のように変更すると:
String longString = readVeryLongString();
String shortString = new String(longString.subString(0, 10));
... は、メソッドshortString
によって返された元の文字列から必要な 10 文字のみをコピーして、新しい内部文字配列を作成した新しい文字列インスタンスになります。subString
この主題を説明する素晴らしい記事:
http://illya-keeplearning.blogspot.cz/2009/03/java-string-internals.html
ドキュメントによると、このコンストラクターは空のシーケンスを作成します。
public String()
Initializes a newly created String object so that it represents an empty character sequence. Note that use of this constructor is unnecessary since Strings are immutable.
空のシーケンスが必要な場合は、理にかなっています。
ただし、通常は、文字列を変更していないため、変更を加える前に空のコンストラクターを使用する必要はありません。実際、たとえば演算子 += を使用して変更すると、別の不変文字列が作成され、変更されません。
この件名に関するこの質問を確認してください: String オブジェクトはどのように機能しますか (不変オブジェクトのように)?
空の文字列を作成するには、デフォルトのコンストラクターを String s new String(); として呼び出します。
文字を含まない String のインスタンスを作成します。