Javaは値渡しであり、参照渡しではありません。

はじめに

多くのJavaプログラマーは、Javaが値渡しであるのか参照渡しであるのか疑問を抱いています。この記事では、なぜJavaが常に値渡しであるのかをまとめています。

最初に、「値渡し」と「参照渡し」はどういう意味ですか? (Saisho ni, “atamawatashi” to “sankōwatashi” wa dō iu imi desu ka?)

  • Pass by value: The method parameter values are copied to another variable and then the copied object is passed to the method. The method uses the copy.
  • Pass by reference: An alias or reference to the actual parameter is passed to the method. The method accesses the actual parameter.

これらの用語についての混乱は、Javaにおけるオブジェクト参照の概念によるものです。厳密に言えば、Javaは常に値渡しです。なぜなら、変数がオブジェクトへの参照を保持していても、そのオブジェクト参照はメモリ上のオブジェクトの位置を表す値です。したがって、オブジェクト参照も値渡しされます。

参照データ型とプリミティブデータ型の両方は値によって渡されます。Javaのデータ型について詳しく学びましょう。

Javaのデータ型を理解するだけでなく、Javaにおけるメモリ割り当ても理解することが重要です。というのも、参照データ型とプリミティブデータ型は異なる方法で格納されるからです。

バリューによるパスのデモンストレーションを行います。

以下の例は、Javaで値が渡される方法を示しています。

次のクラスを使用したサンプルプログラムです。

public class Balloon {

	private String color;

	public Balloon() {}
	
	public Balloon(String c) {
		this.color = c;
	}
	
	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
}

次の例のプログラムは、2つの変数を入れ替える汎用メソッドであるswap()を使用します。また、もう一つのメソッドであるchangeValue()は、変数の値を変更しようとします。

public class Test {

	public static void main(String[] args) {

		Balloon red = new Balloon("Red"); // memory reference = 50
		Balloon blue = new Balloon("Blue"); // memory reference = 100
		
		swap(red, blue);
		System.out.println("After the swap method executes:");
		System.out.println("`red` color value = " + red.getColor());
		System.out.println("`blue` color value = " + blue.getColor());
		
		changeValue(blue);
		System.out.println("After the changeValue method executes:");
		System.out.println("`blue` color value = " + blue.getColor());
		
	}

	// Generic swap method
	public static void swap(Object o1, Object o2){
		Object temp = o1;
		o1 = o2;
		o2 = temp;
	}

	private static void changeValue(Balloon balloon) { // balloon = 100
		balloon.setColor("Red"); // balloon = 100
		balloon = new Balloon("Green"); // balloon = 200
		balloon.setColor("Blue"); // balloon = 200
	}

}

例のプログラムを実行すると、以下の出力結果が表示されます。

Output

After the swap method executes: ‘red’ color value = Red ‘blue’ color value = Blue After the changeValue method executes: ‘blue’ color value = Red

出力結果からは、swap()メソッドが元のオブジェクトの色の値を交換していないことがわかります。これは、Javaは値渡しであることを示しています。なぜなら、swap()メソッドは元のオブジェクト参照値のコピーのみを操作するからです。

どんなプログラミング言語でも、このswap()メソッドのテストは、渡された値による方法か参照による方法かを確認するために使用することができます。

swap()メソッドの使用例を説明します。

クラスのインスタンスを生成するために新しいオペレータを使用すると、オブジェクトが作成され、変数はオブジェクトの保存されたメモリ上の位置を含んでいます。

Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");

以下は、swap()メソッドが実行される際に何が起こるかをステップバイステップで説明します。

  • Assume that red is pointing to memory location 50 and blue is pointing to memory location 100, and that these are the memory locations of both Balloon objects.
  • When the class calls the swap() method with the red and blue variables as arguments, two new object variables, o1 and o2, are created. o1 and o2 also point to memory locations 50 and 100 respectively.
  • The following code snippet explains what happens within the swap() method:
    public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100
    Object temp = o1; // assign the object reference value of o1 to temp: temp = 50, o1 = 50, o2 = 100
    o1 = o2; // assign the object reference value of o2 to o1: temp = 50, o1 = 100, o2 = 100
    o2 = temp; // assign the object reference value of temp to o2: temp = 50, o1 = 100, o2 = 50
    } // method terminated
  • The values of o1 and o2 are swapped, but because the values are copies of the red and blue memory locations, there is no change to the values of the red and blue color values.

変数にはオブジェクトの参照が含まれているため、参照を渡していると思いがちであり、Javaは参照渡しをしていると誤解することがよくあります。しかし、実際には参照のコピーである値を渡しており、そのため値渡しです。

「changeValue()」メソッドの例について解説します。

例プログラムの次のメソッドは、blue変数で参照されるオブジェクトの色の値を変更します。

private static void changeValue(Balloon balloon) { // balloon = 100
	balloon.setColor("Red"); // balloon = 100
	balloon = new Balloon("Green"); // balloon = 200
	balloon.setColor("Blue"); // balloon = 200
}

以下は、changeValue() メソッド内で行われる手順の詳細です。

  • The class calls the changeValue() method on the blue variable that references memory location 100. The first line creates a reference that also points to memory location 100. The color value of the object at memory location 100 is changed to “Red”.
  • The second line creates a new object (with color value “Green”). The new object is at memory location 200. Any further methods executed on the balloon variable act upon the object at memory location 200, and don’t affect the object at memory location 100. The new balloon variable overwrites the reference created in line 1 and the balloon reference from line 1 is no longer accessible within this method.
  • The third line changes the color value of the new Balloon object at memory location 200 to “Blue”, but does not affect the original object referenced by blue at memory location 100. This explains why the final line of the example program output prints blue color value = Red, which reflects the change from line 1.

結論

この記事で、なぜJavaが値渡しであるかについて学びました。さらにJavaのチュートリアルで学習を続けてください。

コメントを残す 0

Your email address will not be published. Required fields are marked *