はじめに
Java初心者がつまずきやすいポイントのひとつが、「値渡しと参照渡しの違い」です。
この記事では、具体的なJavaコードを使って、基本データ型・配列・クラスのインスタンスがメソッドに渡されたときの挙動をわかりやすく解説します。
結論から言うと
Javaはすべて「値渡し」です。
ただし、「参照型の値」が渡される場合、それがシャローコピー(浅いコピー)のように振る舞うため、まるで「参照渡し」のように見えることがあります。
サンプルコード
以下のコードを使って、具体的に違いを見てみましょう。
Main.java
public class Main {
public static void main(String[] args) {
int num = 50;
modifyPrimitive(num);
System.out.println("num = " + num); // → 50(変わらない)
int[] array = { 10, 20, 30 };
modifyArray(array);
System.out.println("array[0] = " + array[0]); // → 20(変わる)
Sample obj = new Sample();
obj.num = 100;
modifyObject(obj);
System.out.println("obj.num = " + obj.num); // → 200(変わる)
}
// 基本型(プリミティブ型)intを受け取る
private static void modifyPrimitive(int value) {
value *= 2;
}
// 配列(参照型)を受け取る
private static void modifyArray(int[] arr) {
if (arr != null && arr.length > 0) {
arr[0] *= 2;
}
}
// クラスのインスタンス(参照型)を受け取る
private static void modifyObject(Sample s) {
if (s != null) {
s.num *= 2;
}
}
}
Sample.java
public class Sample {
int num;
}
出力結果
num = 50
array[0] = 20
obj.num = 200
解説:なぜ結果が違うのか?
1. int num = 50 の場合 → 値渡し(変わらない)
modifyPrimitive
メソッドに渡されるのは、変数 num
のコピー(値)です。
メソッド内で value *= 2;
をしても、元の num
は一切変更されません。
value *= 2; // コピーの変更 → 呼び出し元には影響なし
2. int[] array = {10, 20, 30} の場合 → 配列は参照型(中身が変わる)
modifyArray
メソッドには、配列の参照(アドレスの値)が渡されます。
そのため、メソッド内で配列の中身を変更すると、呼び出し元でもその変更が反映されます。
arr[0] *= 2; // 配列の中身を書き換えている → 呼び出し元にも反映
3. Sample obj = new Sample() の場合 → オブジェクトも参照型(中身が変わる)
modifyObject
メソッドでは、インスタンスの参照が渡されます。
その参照を使ってオブジェクトのフィールド num
を変更すれば、元のオブジェクトにも影響が出ます。
s.num *= 2; // 参照経由でフィールド変更 → 呼び出し元に影響あり
値渡しと参照渡しの本質
データ型 | Javaでの渡され方 | 呼び出し元のデータに影響するか |
---|---|---|
int などの基本型 | 値渡し(コピー) | ❌ 影響しない |
int[] (配列) | 値渡し(参照のコピー) | ✅ 中身は変更される |
オブジェクト(クラス) | 値渡し(参照のコピー) | ✅ フィールドは変更される |
- Javaはポインタを直接操作しない安全な言語です。
- すべて「値渡し」ですが、「参照の値を渡す」ことで、オブジェクトや配列の中身は変えられるのです。
シャローコピーとの関係
シャローコピー(浅いコピー)とは、オブジェクトの参照だけをコピーすることです。
Javaで配列やオブジェクトをメソッドに渡す際、この参照のコピーが渡されるため、メソッド内での変更が呼び出し元にも反映されるのです。
まとめ
- Javaではすべての引数は「値渡し」
- ただし「参照型」の値が渡されると、その中身は変更できる
- 基本型(
int
など)は安全、配列やオブジェクトは注意