Java は本当に参照渡しをサポートしていますか?
そうでない場合、同じ参照を持つ 2 つのオブジェクトを見つけるための == 演算子があるのはなぜでしょうか?
Java は本当に参照渡しをサポートしていますか?
そうでない場合、同じ参照を持つ 2 つのオブジェクトを見つけるための == 演算子があるのはなぜでしょうか?
Javaは参照渡しではなく値渡しを使用します...
ただし、非プリミティブ型の場合、値は参照の値です。
したがって、== はオブジェクトの参照の値を比較します。
区別のポイントは、「参照によるパス** 」と「 **参照の受け渡し」の違いです。また、「call-by-...」と「pass-by-...」が同じ意味で使用されていることもあります。簡単にするために、「pass-by-...」を使用します。
アカデミック、オールドスクール、FORTRAN関連、comp-sciの用語では、参照渡しとは、呼び出されたコードが呼び出し元から渡された変数にアクセス(参照)できることを意味します。呼び出されたコードの仮パラメータに割り当てると、実際には呼び出し元の変数に割り当てられます。違いは、(とりわけ)値渡しです。これにより、呼び出されたコードに、呼び出し元に認識されているデータ(データが何であれ)のコピーが与えられます。
現代のJava関連のOOの世界では、オブジェクトへの「参照を持つ」とは、オブジェクト自体に到達できることを意味します。これは、参照に対して「ポインタ演算」を行わないことを(とりわけ)強調するために「ポインタを持つ」とは区別されます。(実際、この意味での「参照」は、必ずしも実際のポインタのようなメモリアドレスである必要はありません。)
Javaは(最初の意味で)値によって引数を渡しますが、オブジェクト引数の場合、値は(2番目の意味で)参照です。違いに依存するコードを次に示します。
// called
public void munge(List<String> a0, List<String> a1) {
List<String> foo = new List<String>(); foo.add("everybody");
a0.set(0, "Goodbye");
a1 = foo;
}
// caller
...
List<String> l0 = new List<String>(); l0.add("Hello");
List<String> l1 = new List<String>(); l1.add("world");
munge(l0, l1);
...
から戻るmunge
と、呼び出し元の最初のリストにl0
はが含まれます"Goodbye"
。そのリストへの参照がに渡されmunge
、参照されたオブジェクトの変更メソッドが呼び出されました。(つまり、変更された文字列リストへの参照である、の値のコピーa0
を受け取りました。)l0
ただし、から戻るmunge
と、呼び出し元の2番目のリストには、渡されたオブジェクト参照(の値、値によって渡された)でメソッドが呼び出されなかったため、まだ含まl1
れています。代わりに、引数変数が新しい値に設定されました(ローカルオブジェクト参照もで保持されます)。"world"
l1
munge
a1
foo
Javaが参照渡しを使用していた場合、戻り時に、変数を参照し、その値のコピーに単純に初期化されなかっためl1
含ましたがって、への割り当てはへの割り当てでもあります。"everybody"
a1
l1
a1
l1
この同じ問題は、状況を説明するためにASCIIアートを使用して別の質問で議論されました。
Javaは参照渡しではなく、値渡しを使用します。プリミティブ値パラメーターは、オブジェクトへのポインターと同様にスタックにコピーされます。
演算子は、==
プリミティブ値の比較とオブジェクト参照の比較に使用する必要があります。
短い答えはノーです。Java では値渡しのみがあり、オブジェクト (例: Object obj = new Object();
) を操作しているときは、オブジェクト参照を操作しています。値渡しされます。
詳細については、次を参照してください: Java でのパラメーターの受け渡し