複数の同じオブジェクトのインスタンス化


8

同じオブジェクトを複数回インスタンス化すると、Javaで正確に何が起こりますか?

例えば:

Test test = new Test();

その後、私はそれをもう一度、Test test = new Test();もう一度、またはループ内で呼び出します。以前のインスタンス化は破棄されますか?

回答:


16
  1. 各呼び出しnew Test()は、の新しいオブジェクトインスタンスを作成しますTestクラスの
  2. test = new Test();参照を割り当てます変数にそのオブジェクトのtest
  3. 繰り返されるステートメントtest = new Test()は、の2番目のインスタンスを作成し、Testそれをtest再び変数に代入するため、最初の参照が置き換えられます。

ただし、最初のインスタンス化が破棄されるかどうかは、状況によって異なります。Javaランタイム環境は参照をトレースするため、使用中のオブジェクトへの参照がある限り、オブジェクトは破棄されません。たとえば、ステップ2とステップ3の間で最初のインスタンス化への参照が別の場所(などTest test2 = test;)に保存され、ステップ3が発生したときにその変数がまだスコープ内にある場合、test2はまだ参照を保持しているため、最初のオブジェクトは破棄されませんそれに。ただし、そのようなステートメントがなく、ステップ3で最初のオブジェクトへの唯一の参照が省略されると、そのオブジェクトの破棄が行われます。

破棄自体はすぐには行われませんが、後でガベージコレクターが実行されたときに行われることに注意してください。しかし、それは議論されたコードのセマンティクスから独立しています。それはメモリとパフォーマンスの問題だけです。


4
JVMは参照カウントを行いませ。厳密に言うと、仕様はガベージコレクションの実装方法(またはそのことさえ)を規定していませんが、すべての主流のJVMは何らかのトレースコレクターを使用しています。
Michael Borgwardt 2012

@MichaelBorgwardt:あなたのコメントのために私の答えを変更しました。
Doc Brown

if between step 2 and step 3 the reference to the first instantiation is stored somewhere else (like Test test2 = test;), and that variable is still in scope when step 3 occurs...これはやや面倒ですが、ガベージコレクションはスコープではなく到達可能性に基づいています。変数がスコープ内にある可能性がありますが、その値は使用されなくなり、その値はガベージコレクションされる可能性があります。ガベージコレクターには、それに基づいて決定を行うのに便利なスコープがありません。
Doval

@ドヴァル:同意します、このコメントは奇抜です;-)
Doc Brown

5

1:言い回し:オブジェクトをまったくインスタンス化せず、クラスをインスタンス化します。クラスのインスタンス化の結果はオブジェクト(インスタンスとも呼ばれます)です。もちろん、インスタンス化のたびに新しい異なるオブジェクトを作成するために必要な回数だけクラスをインスタンス化できます。

2:何であれ、あなたが提案するコードを持てない:

Test test = new Test();
Test test = new Test();

どちらもこれを持つことはできません:

for (i=0; i<3; i++) {
    Test test = new Test();
    Test test = new Test();
}

部分Test testtest(型のTest)変数の宣言であり、Javaを含む言語は同じスコープ内で同じ変数を2回宣言することを許可しないため、コンパイルは行われません。

ただし、次のように、(名前が示すように)異なるオブジェクトを使用して同じ変数を複数回割り当てることができます。

Test test = new Test();
test = new Test();

最初の行はtest、新しく作成されたオブジェクトを宣言して割り当てます。2行目testも、新しく作成された別のオブジェクトに割り当てます。

また、Javaではショートカットが許可されています。

for (i=0; i<3; i++) {
    Test test = new Test();
}

このループはtest3回宣言しません。test一度だけ宣言される変数に、3つの新しいオブジェクトを順番に割り当てると理解されています。(前のループと比較してください)。

3:変数testとタイプの2つのオブジェクトはTestどうなりますか?

変数にtestは、最初にオブジェクトの参照が割り当てられ、次に別のオブジェクトの参照が割り当てられます。変数は、最後に割り当てられた参照のみを保持します。

タイプの最初のオブジェクトはもうTest割り当てられていtestません。他の変数に参照が割り当てられていない場合、プログラムからこのオブジェクトにアクセスすることはできないため、役に立ちません。システムによるガベージコレクションの対象になります。ある時点で、システム(JVM)はガベージコレクターを実行し、メモリからそれをクリアします。

2番目のオブジェクトは、少なくとも1つの変数がそれを参照している限り存続し、ガベージコレクターもそれを処理して、参照されていないオブジェクトの墓地に移動します。それがJavaオブジェクトの真の生活です:-(


私はたまたまクラスでその間違いを見つけました。クラスには、次のように宣言されたプロパティがあります。WindowManager wm = new WindowsManager(); 次に、プログラマーがこのプロパティを使用していたが誤って書き込んだメソッド:WindowManager wm = new WindowsManager(); 再び。コンパイルだけでなく実行もできます!! 警告はまったくなく、もちろんテストであるアプリケーションはうまく機能していませんでした。次に、それがメソッドスコープ内にオブジェクトを作成していて、プロパティが変更されないことに気付きました。だから注意してください
リッカー・シルバ

1
あなたが完全に説明したように、これは同じ変数の再割り当てではありません。同様のシャドウイングの間違いは、あなたが忘れてしまった場合、パラメータを使用するときに発生する可能性がthisコンストラクタのように、キーワードを:this.name = name

-1

短い答え:誰も指し示していない場合、以前に作成されたオブジェクトはすべて破棄されます。テストがそれを参照するため、最新のものだけが存在します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.