首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 參數傳遞真相:只有「傳值」,沒有「傳參考」——基本型別與物件參考的記憶體模型深度解析

     編輯:Java 程式設計入門

結論先行

Java 永遠是「傳值呼叫」。 基本型別傳遞值的副本;物件傳遞「參考的副本」(reference value copy)。不存在 C++ 的傳參考。

第一類:基本型別 —— 傳值無疑

public static void test(boolean flag) {
    flag = !flag; // 修改副本
    System.out.println("方法內: " + flag); // false
}

public static void main(String[] args) {
    boolean flag = true;
    System.out.println("呼叫前: " + flag); // true
    test(flag);
    System.out.println("呼叫後: " + flag); // true(原值未變)
}

記憶體圖:

main 棧框: flag (true)  ──值複製──►  test 棧框: flag (true) → 改為 false

第二類:什麼是參考?

  • 參考 = 物件在堆上的地址(類似 C 指標,但不可算術運算、不可直接觀察數值)。
  • 參考本身佔用記憶體(通常 32/64 位元),是一種資料型別,非物件本身。
  • 多個參考可指向同一物件:
String a = "Hello";
String b = a; // a、b 參考值相同,指向同一 "Hello" 物件

StringBuffer sb1 = new StringBuffer("Hello");
StringBuffer sb2 = sb1;
sb2.append(", World");
System.out.println(sb1); // "Hello, World" —— 同一物件被修改

第三類:物件參數怎麼傳?

public static void modify(StringBuffer sb) {
    sb.append(", World"); // 透過參考副本修改「同一物件」
    // sb = new StringBuffer("New"); // 重新指向新物件 → 不影響呼叫端
}

public static void main(String[] args) {
    StringBuffer sb = new StringBuffer("Hello");
    modify(sb);
    System.out.println(sb); // "Hello, World"
}

記憶體圖:

main 棧框: sb ──────┐
                    ▼ (參考值複製)
modify 棧框: sb ────┼──► 堆上同一 StringBuffer 物件
                    │
                    └── sb = new ... 只改變 modify 棧框的參考,斷開連結

為什麼會有「傳參考」的錯覺?

  1. 物件屬性可透過參考副本修改 → 看起來像傳參考。
  2. 但重新指派參數變數(param = new Obj())絕不影響呼叫端。
  3. C++ void f(T& ref) 才是真正傳參考:重新指派會改變呼叫端變數綁定的物件。

實務啟示

  • 不可變物件:String、Integer、LocalDate… 透過參考也無法修改 → 行為等同傳值,安全共享。
  • 可變物件:ArrayList、StringBuilder、自訂 Bean… 若不想被修改,需防禦性複製(new ArrayList(list)、Collections.unmodifiableList)。
  • 方法設計:明確文件化「是否會修改傳入物件」、「是否會保留參考」。

進階:Java 如何模擬「輸出參數」?

  1. 回傳多值物件:return new Result(a, b); 或 Map/Record。
  2. 傳入可變容器:List out = new ArrayList<>(); fill(out);
  3. 傳入單元素陣列:int[] out = new int[1]; compute(out);(不推薦,可讀性差)。
  4. 回呼介面:void compute(Callback cb) { cb.onResult(val); }
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved