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

Java 參數傳遞機制深度解析:基本型別 vs 物件參考與 static 方法行為

     編輯:Java 程式設計入門

核心結論

Java 唯一採用 值傳遞。
— 基本型別:傳遞值的副本,方法內修改不影響外部。
— 參考型別:傳遞參考的副本(記憶體位址),方法內可透過參考修改物件內部狀態,但無法替換呼叫端的參考變數指向。

三大經典測試場景


public class ParamTest {
    public static void main(String[] args) {
        // 測試 1:基本型別
        double percent = 10;
        System.out.println("Before: " + percent); // 10
        tripleValue(percent);
        System.out.println("After:  " + percent); // 10 —— 未改變

        // 測試 2:物件狀態修改
        Employee harry = new Employee("Harry", 50000);
        System.out.println("Before: " + harry.getSalary()); // 50000
        tripleSalary(harry);
        System.out.println("After:  " + harry.getSalary()); // 150000 —— 物件內部狀態被改變

        // 測試 3:嘗試交換參考
        Employee a = new Employee("Alice", 70000);
        Employee b = new Employee("Bob", 60000);
        System.out.println("Before a: " + a.getName()); // Alice
        System.out.println("Before b: " + b.getName()); // Bob
        swap(a, b);
        System.out.println("After a:  " + a.getName()); // Alice —— 未交換成功
        System.out.println("After b:  " + b.getName()); // Bob
    }

    // 基本型別:修改的是區域變數副本
    public static void tripleValue(double x) {
        x = 3 * x;
    }

    // 物件參考:修改物件內容(透過參考副本)
    public static void tripleSalary(Employee x) {
        x.raiseSalary(200); // 薪資漲 200%
    }

    // 物件參考:嘗試交換參考——失敗
    public static void swap(Employee x, Employee y) {
        Employee temp = x;
        x = y;      // 僅改變區域參考副本
        y = temp;   // 呼叫端 a、b 完全不受影響
    }
}

class Employee {
    private String name;
    private double salary;
    public Employee(String n, double s) { name = n; salary = s; }
    public String getName() { return name; }
    public double getSalary() { return salary; }
    public void raiseSalary(double byPercent) { salary += salary * byPercent / 100; }
}

記憶體模型圖解

呼叫端棧框                          方法棧框
┌─────────────────┐                 ┌─────────────────┐
│ percent = 10    │  值複製  ───►   │ x = 10          │
└─────────────────┘                 └─────────────────┘

呼叫端棧框                          方法棧框          堆
┌─────────────────┐                 ┌─────────────────┐
│ harry ──────────┼── 參考複製 ──►  │ x ──────────────┼──► Employee("Harry", 50000)
└─────────────────┘                 └─────────────────┘
                                                         ▲
                                                 同一物件,狀態可改

呼叫端棧框                          方法棧框
┌─────────────────┐                 ┌─────────────────┐
│ a ──────────────┼── 參考複製 ──►  │ x ──────────────┐
│ b ──────────────┼── 參考複製 ──►  │ y ──────────────┤
└─────────────────┘                 └─────────────────┘
  swap 內部交換 x、y 參考,呼叫端 a、b 參考完全不變

static 方法特殊性澄清

  • static 方法不改變參數傳遞語義,仍是值傳遞。
  • static 方法屬於類、不屬於實例,無法直接存取非 static 欄位/方法,但能正常接收參數並操作參考物件。
  • 原文提到「static 方法不能對物件產生效果」錯誤——tripleSalary(harry) 正是 static 方法成功修改物件狀態的例證。

常見面試陷阱與對策

實務建議

  1. 不可變物件優先:傳遞 String、LocalDate、Guava ImmutableList 等,天然安全。
  2. 防禦性複製:建構子/Setter/Getters 涉及可變物件時,複製副本(new ArrayList<>(list)、date.clone())。
  3. 方法簽名語意化:需修改呼叫端集合內容用 void addAll(Collection<E> c);需替換整個集合回傳 List<E> newList()。
  4. 避免「交換參考」需求:改回傳新物件、使用 AtomicReference、或封裝在可變容器(如單元素陣列 Holder<T>)中。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
程式碼片段結果原因
void m(String s) { s = "new"; }
String a = "old"; m(a);
a 仍為 "old"String 不可變,參數 s 重新指向新字串,呼叫端 a 不變
void m(StringBuilder sb) { sb.append("x"); }
StringBuilder b = new StringBuilder("a"); m(b);
b 變 "ax"同一可變物件,透過參考副本修改內容
void m(int[] arr) { arr = new int[5]; }
int[] a = {1,2}; m(a);
a 仍指向 {1,2}參數 arr 重新指向新陣列,呼叫端 a 不變
void m(int[] arr) { arr[0] = 99; }
int[] a = {1,2}; m(a);
a 變 {99,2}同一陣列物件,修改元素內容