人々が鋭く指摘しているように、Javaは常に価値によって渡されます。
オブジェクトの「値」は、ヒープに格納されているメモリアドレスです。だからここに何が起こるかです:
Object o = new Object();
右側はヒープにスペースを割り当てます。場所1000と言います。左側はスタックに変数を割り当てます。場所100と言います。割り当てにより、オブジェクトの「値」が含まれます。これは1000で、ヒープ上の場所です。あなたの記憶は次のようになります:
Stack
---------------------------
====== caller stack frame ====
100(o) ==> 1000
==============================
Heap
------------------------------
1000 ==> object data 1
次に、メソッド呼び出しを行います。
void foo(Object x) { .... }
foo(o);
メソッド呼び出し用に新しいスタックフレームが(明らかにスタック上に)作成されます。新しい変数がスタック上、たとえば場所200に作成され、渡されたオブジェクトの「値」(1000)が与えられると、そのオブジェクトはヒープ上の場所になります。
したがって、メソッドが実際にコードを実行する前のメモリは次のようになります
Stack
---------------------------
====== caller stack frame ====
100(o) ==> 1000
==============================
====== foo stack frame =======
200(x) ==> 1000
==============================
Heap
------------------------------
1000 ==> object data 1
したがって、これをメソッドで実行すると、次のようになります。
void foo(Object x) {
x = new Object();
}
たとえば、場所2000で新しいオブジェクトをヒープに割り当て、その場所にメソッドパラメータ変数を割り当てて、メモリが次のようになるようにします。
Stack
---------------------------
====== caller stack frame ====
100(o) ==> 1000
==============================
====== foo stack frame =======
200(x) ==> 2000
==============================
Heap
------------------------------
1000 ==> object data 1
2000 ==> object data 2
そして、メソッドが終了すると、スタックフレームが削除され、次の状態に戻ります。
Stack
---------------------------
====== caller stack frame ====
100(o) ==> 1000
==============================
Heap
------------------------------
1000 ==> object data 1
2000 ==> object data 2
「o」は引き続き同じオブジェクトデータを指していることに注意してください。2番目に割り当てられたオブジェクト(場所2000)も、ガベージコレクションの対象になります。