Java 是按值传递,而不是按引用传递

簡介

許多Java程序員懷疑Java是按值傳遞還是按引用傳遞。本文概述了為什麼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;
	}
}

以下示例程序使用了一個通用方法swap(),該方法交換兩個變量。另一個方法changeValue()嘗試更改變量的值。

public class Test {

	public static void main(String[] args) {

		Balloon red = new Balloon("Red"); // 內存參考 = 50
		Balloon blue = new Balloon("Blue"); // 內存參考 = 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());
		
	}

	// 通用交換方法
	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()方法的示例

當您使用new運算符創建類的實例時,對象將被創建並且變量包含對象保存的內存中的位置。

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

這裡是swap()方法執行時發生的步驟詳細說明:

  • 假設red指向內存位置50,blue指向內存位置100,這些是兩個Balloon對象的內存位置。

  • 當類使用redblue變量作為參數調用swap()方法時,將創建兩個新的對象變量o1o2o1o2同樣指向內存位置50和100。

  • 以下的程式碼片段解釋了在 swap() 方法內發生的事情:

    public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100
    	Object temp = o1; // 將 o1 的物件參考值指定給 temp:temp = 50,o1 = 50,o2 = 100
    	o1 = o2; // 將 o2 的物件參考值指定給 o1:temp = 50,o1 = 100,o2 = 100
    	o2 = temp; // 將 temp 的物件參考值指定給 o2:temp = 50,o1 = 100,o2 = 50
    } // 方法結束
    
  • o1 和 o2 的值已交換,但因為這些值是對於紅色和藍色記憶體位置的副本,因此對於紅色和藍色顏色值的值並未更改。

由於變數包含對象的引用,很容易錯誤地認為你正在傳遞引用並且 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()方法中发生的步骤:

  • 该类在blue变量上调用changeValue()方法,该变量引用内存位置100。第一行创建了一个引用,也指向内存位置100。内存位置100处的对象的颜色值被改为"Red"

  • 第二行创建了一个新对象(颜色值为"Green")。新对象位于内存位置200。后续在balloon变量上执行的任何方法都针对内存位置200的对象进行操作,不会影响内存位置100的对象。新的balloon变量覆盖了第1行创建的引用,第1行中创建的balloon引用在此方法内不再可访问。

  • 第三行更改了記憶體位置200的新Balloon對象的顏色值為"Blue",但不影響記憶體位置100的blue引用的原始對象。這解釋了為什麼示例程序輸出的最後一行打印blue color value = Red,這反映了從第1行的變化。

結論

在本文中,您了解了為什麼Java是按值傳遞。通過更多的Java教程繼續學習。

Source:
https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference