必ずつまづくJavaの参照値渡し
Javaにおいて、参照渡しは存在しないとよく聞きます。
最初は「えっ」って思いましたが、調べた結果をまとめました。
一般的なメソッドの引数の渡し方
・値渡し
・参照渡し
・参照値渡し
Javaにおけるメソッドの引数の渡し方
・値渡し
・参照値渡し
※「参照渡し」はJavaでは存在しません。
「値渡し」、「参照値渡し」について、説明していきます。
値渡しの例
RefValHandOver.java
private static void editNumber(int arg){
arg = 0;
System.out.println("editNumber : " + arg);
}
public static void main(String[] args) {
int number = 100;
editNumber(number);
System.out.println( "main : " + number);
}
結果
editNumber : 0
main : 100
editNumber内では0になっているが、main内では100のままで変わらない。
引数をプリミティブ型にした場合は値渡しとなる。
プリミティブ型
型 | bit | 初期値 |
---|---|---|
boolean | 1bit | false |
byte | 8bit | 0 |
char | 16bit | \u0000 |
short | 16bit | 0 |
int | 32bit | 0 |
float | 32bit | 0.0 |
long | 64bit | 0 |
double | 64bit | 0.0 |
ここまでは特に問題ないですよね。
参照値渡しの例
3つのパターンに分類して説明していきます。
・1. メソッド内でデータ操作した場合
・2. メソッド内でnewしなおす。
・3. メソッド内でnullを代入する。
RefValHandOver.java
// 1. メソッド内でデータ操作した場合
private static void methodAddArray(ArrayList<String> arg){
arg.add("B");
System.out.println("methodAddArray : " + arg.hashCode() + " : " + arg.toString());
}
//2. メソッド内でnewしなおす。
private static void methodNewArray(ArrayList<String> arg){
arg = new ArrayList<String>();
arg.add("C");
System.out.println("methodNewArray : " +arg.hashCode() + " : " + arg.toString());
}
//3. メソッド内でnullを代入する。
private static void methodNullArray(ArrayList<String> arg){
arg = null;
System.out.println((arg != null) ? "methodNullArray : " + arg.hashCode() + " : " + arg.toString() : "null");
}
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>() {{add("A");}};
// 1. メソッド内でデータ操作した場合
methodAddArray(arrayList);
System.out.println("main : " + arrayList.hashCode() + " : " + arrayList.toString());
//2. メソッド内でnewしなおす。
methodNewArray(arrayList);
System.out.println("main : " + arrayList.hashCode() + " : " + arrayList.toString());
//3. メソッド内でnullを代入する。
methodNullArray(arrayList);
System.out.println((arrayList != null) ? "main : " + arrayList.hashCode() + " : " + arrayList.toString() : "null");
}
結果
// 1. メソッド内でデータ操作した場合
methodAddArray : 3042 : [A, B]
main : 3042 : [A, B] //参照先が変わっていない
//2. メソッド内でnewしなおす。
methodNewArray : 98 : [C]
main : 3042 : [A, B] //参照先が変わっている
//3. メソッド内でnullを代入する。
methodNullArray : null
main : 3042 : [A, B] //参照先が変わっている
図解してみる
説明してみる
焦点は引数に新しい参照先を___代入___しているかどうかです。
代入されると「main内のローカル変数」と「メソッド内の引数」が別物になってしまいます。
※Javaには存在しない___参照渡し___では2、3の例がmainのローカル変数に反映されます。
まとめ
値渡し、___参照値渡し___について説明してきました。
個人的には参照値渡しを参照先アドレス渡しとしたら、わかりやすいんじゃないかと思います。