
本記事は、Javaを一から学んでいく際の学習メモとして書かれています。
主にインプレスから出版されている「スッキリわかるJava入門 第2版 (スッキリシリーズ)」の内容に沿ったかたちで学習していきます。
今回は、Javaの値渡しと参照渡しについて学んでいきます。
値渡し
int型のような基本データ型(プリミティブ型)で宣言された変数の値を、あるメソッドに引数として渡す場合は、メソッドの仮引数にコピーされた値そのものが渡され、メソッド内でその変数値を変更しようとしても、呼び出し元の実引数である変数には影響しません。
public class PassByValue{
public static void swap(int a, int b){
int tmp = a;
a = b;
b = tmp;
}
public static void main(String[] args) {
int a = 1;
int b = 2;
swap(a, b);
System.out.printf("a=%d\n", a);
// a=1
System.out.printf("b=%d\n", b);
// b=2
}
}
参照渡し
ところが、配列などの参照型と言われるオブジェクトでは、コピーされた値が渡されるのではなく、その先頭アドレスへの参照値が仮引数にコピーされます。
そのため、メソッド内で仮引数にコピーされた参照値を用いて、その中身を操作することが可能です。
public class PassByReference{
public static void change(int[] array){
array[0] = 100;
}
public static void main(String[] args) {
int[] array = {1};
change(array);
System.out.printf("array[0]=%d\n", array[0]);
// array[0]=100
}
}
しかし、メソッド内の仮引数に別のオブジェクトを代入などをした場合は、仮引数が指すオブジェクトへの参照が変更されるのみで、呼び出し元の実引数が参照するアドレスは変更されません。
public class PassByReference{
public static void change(int[] array){
int[] newArray = {100};
array = newArray;
}
public static void main(String[] args) {
int[] array = {1};
change(array);
System.out.printf("array[0]=%d\n", array[0]);
// array[0]=1
}
}
String型と参照
String型も参照型と呼ばれるもので、オブジェクト内部としてはC言語のようにchar型の配列として扱っています。
通常は配列などのnewキーワードで作成したオブジェクトはヒープ領域に存在しますが、String型オブジェクトについてはその作成方法で若干異なるようです。
public class Reference{
public static void main(String[] args) {
String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1 == "hello");
// true
System.out.println(str2 == "hello");
// false
}
}
上記の場合、str1はconstant pool領域に作成され、str2はヒープ領域に作成されます。
参照型を==で比較するということは、保持している先頭アドレスを比較していることになるので、str1では真、str2では偽となります。
また、String型はイミュータブル(変更不可)なオブジェクトのため、文字列自体を書き換えることはできません。
最後に
今回はJavaの値渡しと参照渡しについて、基本的なルールを学びました。
次回はJavaで扱うパッケージについて学んでいきます。
参考書籍