3

Java やその他の言語の文字列オブジェクトなどの不変オブジェクトのメモリ管理に関して、概念的な疑問があります。たとえば、値「Hello」を保持する文字列オブジェクト「str」があり、次のようにします。

String str = "Hello";
str = str.concatenate("World");

この場合、私が理解しているように、状態が「Hello World」の新しい String オブジェクトが作成され、str に参照されます。現在、Java (および他のほとんどのオブジェクト指向言語) では、オブジェクトの寿命はその参照が生きている限りです。では、「Hello」を保持しているオブジェクトはどこに行くのでしょうか。ガベージ コレクタが自由に処理するまでメモリ ヒープに常駐しますか? また、ガベージ コレクタをサポートせず、クラス デストラクタに依存する必要がある言語についてはどうでしょうか。

StringBufferまた、やなどの可変オブジェクトStringBuilderがはるかに柔軟でパフォーマンスに適している場合、言語を設計する際に、そもそもなぜオブジェクトを不変にするのでしょうか?? (つまり、後続のJDKリリースで文字列バッファなどの新しい構造を導入する必要があるのではなく、最初から文字列オブジェクトを変更できないのはなぜですか?)。

誰かがこれについて私を導くことができれば素晴らしいことです。私はこれに慣れていないので、明確で基本的な説明をいただければ幸いです。ありがとう。

4

4 に答える 4

2
So where does the object holding "Hello" go

"Hello" への参照 str には新しい値が割り当てられるため、値 "Hello" への参照は失われますが、まだプール内にあり、利用可能です。ガベージ コレクターはそれを収集してヒープから削除する可能性があります。正確にはわかりません。 、将来のコードでまだ「Hello」文字列を使用しているとしましょう

String againhello= "Hello" ;

この場合、ガベージ コレクターはそれを収集するべきではありません。"Hello" 文字列が作成され、まだ使用されているため、新しい参照のみが割り当てられているためです。

オブジェクトの可変性と不変性の背後にある概念は、2 つのオブジェクトが同じ値を持つ場合、同じハッシュコードを持ち、equals メソッドに対して true を返す必要があることです。これは String オブジェクトに対しても当てはまりますが、パフォーマンスを向上させるために

彼らは String を不変として設定します。たとえば、ヒープが同じ値と異なるオブジェクトの数で満たされることを望まないためです。

String sre="Hello";

String str="Hello"; 

String の不変性がなければ、 heap には 2 つのオブジェクトがありますが、 object は 1 つしかなく、参照変数は 2 つしかありません。

what is difference between String and StringBuilder class. 

StringBuilder クラスが Java 5 に追加され、StringBuffer と同様の機能が提供されました (つまり、変更可能な string )。 string が変更されるたびに、新しいオブジェクトが作成されなくなりました。 StringBuilder を使用する利点は、StringBuffer が同期されているため、StringBuffer よりも比較的高速であることです。クラスですが、StringBuilder はそうではないため、スレッドの安全性が問題にならない環境で StringBuffer を使用する場合は、パフォーマンスを向上させるために StringBuilder を使用することを検討してください。

デフォルトでは、すべての Java クラスは変更可能です。つまり、インスタンスの内容を変更できます。しかし、不変性が提供する利点はほとんどないため ( http://download.oracle.com/javase/tutorial/essential/concurrency/immutable.html )、一部のクラスを final としてマークすることで不変にするのはそのためです。問題のクラスは String クラスと Wrapper クラスであり、それら (不変クラス) について論理的に考えると、提供されたリンクの説明が理にかなっています。2 つのそれぞれに個別に対処しましょう。

String class: 

Kathy Siera と Bert Bates が SCJP の 433 ページで述べたように、アプリケーションが成長するにつれて、プログラムの文字列リテラルに多くの冗長性が生じることは非常に一般的です。したがって、この問題に対処するために、Java の設計者は、使用可能なメモリを効率的に使用してパフォーマンスを向上させる String プールの概念を思いつきました。しかし、ご想像のとおり、いくつかの参照変数が知らないうちに同じ文字列を参照している場合、それらのいずれかが文字列の値を変更できるとしたら、それは悪いことです。したがって、この String クラスを不変にする必要が生じました。

Wrapper classes:

ラッパー クラスを作成する目的の 1 つは、プリミティブをオブジェクト用に予約されたアクティビティ (コレクションへの追加や、オブジェクトの戻り値を持つメソッドから返されるなど) を処理するメカニズムを提供することです。コレクションについて考えると、複数のスレッドからアクセスされることがよくあります。ラッパー クラスが変更可能でない場合、同時変更のリスクが発生し、一貫性のない状態が発生する可能性があります。したがって、競合を避けるために、ラッパー クラスは不変になります。

したがって、一般に、不変クラスに出くわすときはいつでも、そのインスタンスが並行して使用されていると考えるのが論理的です。また、オブジェクトの内容を変更したくない場合 (理由の 1 つは同時アクセスです)、クラスを不変にします。

于 2013-06-06T08:38:29.197 に答える
0

おそらくアウター リム テリトリーでは、Darth Coder と Google が利用できないため、参照オブジェクトとガベージ コレクションの入門レベルの説明を次に示します。

これが Oracle Java VM で正確にどのように機能するかについての技術的な説明は、ここにあります。

どの言語でもガベージ コレクションを理解するための重要なアイデアは、到達可能性です。すべてのオブジェクトは、ルート参照からのパスによって到達可能である必要があります。ルート参照とは 例としては、メソッド呼び出しスタック フレーム、クラス、スレッド、JNI 参照などのチェーンがあります。これらのルートから到達できないものはすべて使用されていないと見なされ、そのスペースは記事で説明されている方法で再利用されます。ガベージ コレクションは決して些細なことではなく、活発な研究分野なので、しばらくお待ちください :-)。

于 2013-06-06T08:35:41.413 に答える