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

Java 參數傳遞機制深度解析:是傳值還是傳引用?

     編輯:Java 相關知識

核心結論先行

Java 中只有傳值(Pass by Value)。這是理解 Java 參數傳遞機制的根本前提。所謂的「傳引用」實質上是「引用的值」被傳遞,即對象在堆內存中的地址值被複製傳遞。

基本類型傳遞:純粹的值拷貝

對於基本類型(int、boolean、double 等),參數傳遞時會在棧幀中創建一個副本。方法內部對參數的任何修改,僅影響副本,不影響原始變量。

public class Test {
    public static void test(boolean test) {
        test = !test;
        System.out.println("In test(boolean) : test = " + test); // false
    }
    public static void main(String[] args) {
        boolean test = true;
        System.out.println("Before test(boolean) : test = " + test); // true
        test(test);
        System.out.println("After test(boolean) : test = " + test);  // true,原值未變
    }
}

引用類型傳遞:傳遞的是「引用的值」

對象在堆中分配內存,變量持有的是對象的地址(引用)。調用方法時,將這個地址值複製一份傳給形參。此時,實參和形參指向同一個堆對象。

情況一:修改對象內部狀態(可影響原對象)

public static void test(StringBuffer str) {
    str.append(", World!"); // 修改對象內容
}
public static void main(String[] args) {
    StringBuffer string = new StringBuffer("Hello");
    test(string);
    System.out.println(string); // 輸出:Hello, World!  原對象被修改
}

解析:形參 str 複製了實參 string 的地址值,兩者指向同一對象。通過形參調用方法修改對象內部字段,實際操作的是堆上同一塊內存。

情況二:重新賦值引用(不影響原引用)

public static void test(String str) {
    str = "World"; // 改變形參指向,指向新對象
}
public static void main(String[] args) {
    String string = "Hello";
    test(string);
    System.out.println(string); // 輸出:Hello  原引用未變
}

解析:str = "World" 只是將形參 str 的局部副本指向新的字符串對象,斷開了與原對象的聯繫,實參 string 仍指向 "Hello"。

為什麼會產生「傳引用」的誤解?

這源於 C/C++ 程序員轉型 Java 時的思維慣性。C 語言有顯式指針,SwapValue(傳值)無法交換變量,SwapPointer(傳指針)可以。Java 無指針,但對象變量本質是隱式指針。當發現方法內能修改對象內容時,誤以為是「傳引用」;實則是「傳遞了引用的值」。

正確的理解框架

  • 基本類型:傳遞數值副本,方法內修改不影響外部。
  • 引用類型:傳遞地址值副本。
    • 若方法內調用對象方法/修改字段 → 影響共享對象。
    • 若方法內對形參重新賦值 (new/賦值) → 僅改變局部引用指向,不影響實參。

實戰建議

設計 API 時,若不希望調用方修改傳入對象,可採用防禦性拷貝(傳入副本)或使用不可變對象。理解「引用值傳遞」本質,有助於避免副作用 Bug,編寫更健壯的代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved