Java では何も参照によって渡されませんが、変数の値が何であるかを知る必要があります。
タイプの変数の値が配列int[]
ではありません。配列への参照です。プリミティブの配列であっても、すべての配列は参照型です。
あなたが書くとき:
int[] x = { 1, 2, 3, 4, 5 };
someMethod(x);
次に、xの値someMethod
が値渡しで に渡されます。これは配列への参照です。メソッドは配列の内容を変更できますが、x
それ自体の値を変更することはできません。これは、Java が参照渡しを使用している場合に可能でした。
式の値が参照またはプリミティブ値のいずれかであることを理解すると、多くのことがより明確になります。たとえば、次のコードを見てください。
int[] x = { 1, 2, 3, 4, 5 };
int[] y = x;
y[0] = 10;
System.out.println(x[0]);
結果はどうなると思いますか?代入演算子は値を RHS から LHS にコピーします。つまり、x
とy
は同じ配列への参照です。したがって、最終行は 10 を出力します。この「値のコピー」は、引数の受け渡しに使用される原則とまったく同じです。
ここに矛盾はありません。何が起こっているのか、そして値渡しと参照渡しが実際に何を意味するのかを理解する必要があるだけです。
編集:これについてまだ疑問があることに本当に驚いています。
Java 言語仕様のセクション 8.4.1 (Formal Parameters)から:
メソッドまたはコンストラクターが呼び出されると (§15.12)、実引数式の値は、メソッドまたはコンストラクターの本体の実行前に、新しく作成されたパラメーター変数、宣言された Type のそれぞれを初期化します。
これは実質的に、値渡しセマンティクスの定義です。引数の値は、パラメーターの初期値として使用されます。
これらの値は参照である場合もあれば、プリミティブな値である場合もあります。渡される値であるという事実は変わりません。
編集:あなたが使用する定義は、私の見解では表現が悪いですが、Javaがすべてを値で渡すと主張することが誤解を招くという意味ではありません。
値渡しの場合は次のようになります。
これは変数のコピーを作成し、変数が配列のように大きい場合は非常に遅く非効率になる可能性があります。
C と C++ について話していたことに注意してください (ただし、実際には C++ にも参照渡しがあります) 。variable のコピーを作成することについて説明しています。それはまさに Java が行うことです。違いは、Java では、変数の値が常にプリミティブ値または参照のいずれかであるということです。決して物ではありません。
この重要な点を理解すれば(引数の受け渡しだけでなく重要な点でもあります)、Java はすべてを値渡しであると正しく言うのはまったく簡単です。メソッドまたはコンストラクターが呼び出されると、引数が評価され、値がパラメーターの初期値として使用されます。これは値渡しであり、Java がすべてのパラメーターに対して行うことです。
リンク先の PDF については、IMO というトピックについての恥ずべき議論です。それは参照渡しの意味を混乱させ、正当な理由もなく String を特殊なケースにします (String はたまたま不変ですが、他のクラスもそうである可能性があります)。私の見解を裏付けるリンクをいくつか提供すると役に立ちますか?
さらに何百もあります。これに戸惑うのはあなたが初めてではありませんが、Java は実際にはすべてを値渡しします。参照も同様です。