網頁

2019/1/26

Java 是pass-by-value(傳值)還是pass-by-reference(傳址/傳參考)

Javapass-by-value(傳值),不是pass-by-reference(傳址/傳參考)。


通常對原始型別的參數值傳遞比較沒什麼疑問,是pass-by-value;但對於物件參數的傳遞就容易感到混淆,常誤以為是pass-by-reference,但Java物件參數的傳遞其實也是pass-by-value。

會混淆是因為沒弄清楚pass-by-reference的意思:

  • pass-by-value的意思是將參數值複製後傳遞。
  • pass-by-reference的意思是傳遞原本的參數值。

簡單說,pass-by-value和pass-by-reference的差別在於傳遞的是「複製的參數」還是「原本的參數」,若傳遞的是複製的參數則為pass-by-value,若沒複製而是傳遞原來的參數則為pass-by-reference。

public class Main {

    public static void main(String[] args) {
        A a1 = new A(1);
        System.out.println("a1:" + a1.getN()); // a1:1

        modify(a1);

        System.out.println("a1:" + a1.getN()); // a1:3
    }

    static void modify(A a) {
        a.setN(3);
        System.out.println("a:" + a.getN()); // a:3
    }
}

class A {

    private int n;

    public A(int n) {
        this.n = n;
    }

    public int getN() {
        return n;
    }

    public void setN(int n) {
        this.n = n;
    }

}

你可能會覺得奇怪,傳入方法a物件參數的值一旦被修改,a1.n的值也會同時改變,因為a1a兩著都有一樣的參照(reference),應該是pass-by-reference才對吧?

其實上面的情況是,「參照(reference)的pass-by-value的傳遞」,而不是pass-by-reference。這細微的查別在於當呼叫modify(A a)時是將a1的reference複製然後傳給a,因此a1a會擁有相同「內容」的reference(但並不是同一個reference),即所指的位置相同,所以修改a1.n時,a.n也會被修改。而不是將a1參照所指的真正的內容(物件)傳給a,因為Java變數僅儲存物件的參照,而非物件本身。

總之記住Java是pass-by-value,不是pass-by-reference。


沒有留言:

張貼留言