Javaの値渡しと参照渡し

基本型

Javaのメソッドの引数に与えられる値は基本的に値渡しです。
値渡しというのは、引数に与えられた値がコピーされるということです。
なので、メソッド内で引数に対して変更が加えられても、それは引数のコピーに対して変更を加えていることになります。

そのため、以下のような動きになることは理解できると思います。

int count = 8;
plus(count);
Log.d(count);

void plus(int value) {
    int result = value * 2;
    Log.d(result);
}
after applying plus 16
outside of method plus 8

参照型

参照型を引数に渡すと、参照値がコピーされます。

以下のコードで言えば、左辺が参照値で右辺が実際の値です。
左辺の参照値というのは例えていうと、右辺の実際の値が格納されているメモリの番地のことです。

List<String> list = new ArrayList<>();

東京都千代田区千代田1−1には皇居があります。
東京都千代田区千代田1−1が参照値で、皇居が実際の値みたいな関係です。

上記を踏まえて、以下のプログラムを考えてみたいと思います。

List<String> japanese = new ArrayList<>();
japanese.add("すぎた");
plusElementJ(japanese);
Log.d(japanese.toString());

void plusElementJ(List<String> list) {
    list.add("おはよう");
    Log.d(list.toString());
}
[すぎた, おはよう]
[すぎた, おはよう]

上記のプログラムでは、一二行目で 東京都千代田区千代田1−1に皇居があることを宣言しています。
メソッドに東京都千代田区千代田1−1の住所を渡します。
メソッド内では、受け取った住所に対して、増築を行いました。
すると、メソッドをでても、東京都千代田区千代田1−1には皇居とそれを増築した結果があるのは納得できましたね。

Stringも参照型だけど。。。

String name = "すぎた";
concatenate(name);
Log.d(name);

void concatenate(String name) {
    name = "おはよう、" + name;
    Log.d(name);
}
after applying concatenate おはよう、すぎた
outside of method concatenate すぎた

Stringは参照型ではありますが、immutableです。つまり変更不可能です。
そのため、この処理は内部的には以下のように新しいStringオブジェクトが作られているんじゃないでしょうか?

name = new String("おはよう、"  + name)

そのため、以下のようなことが起こっていると思います。

  1. コピーされている参照値 nameには新しい参照値が代入される
  2. nameが新しく参照している参照値に新しくオブジェクトが作成される

参考

もう参照渡しとは言わせない

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です