Java方法的值傳遞機制學習筆記
基本概念
形參和實參
- 形參:在定義方法時,方法名后面括號()中聲明的變量稱為形式參數,簡稱形參。
- 實參:在調用方法時,方法名后面括號()中使用的值、變量、表達式都稱為實際參數,簡稱實參。
值傳遞規則
- 規則:實參給形參賦值的過程
- 如果形參是基本數據類型的變量,則將實參保存的數值賦值給形參
- 如果形參是引用數據類型的變量,則將實參保存的地址賦值給形參
代碼案例
1. 基本數據類型傳遞示例
public class PrimitiveTypeExample {
public static void modifyValue(int x) {
System.out.println("方法內修改前 - x = " + x); // 輸出:10
x = 20; // 修改形參的值
System.out.println("方法內修改后 - x = " + x); // 輸出:20
}
public static void main(String[] args) {
int num = 10;
System.out.println("調用方法前 - num = " + num); // 輸出:10
modifyValue(num); // 傳遞的是num的數值副本
System.out.println("調用方法后 - num = " + num); // 輸出:10(不變)
}
}
2. 引用數據類型傳遞示例
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class ReferenceTypeExample {
// 修改對象狀態 - 會影響原始對象
public static void modifyPerson(Person p) {
System.out.println("方法內修改前 - " + p.name + ", " + p.age);
p.age = 30; // 修改對象內容
p.name = "李四";
System.out.println("方法內修改后 - " + p.name + ", " + p.age);
}
// 重新賦值引用 - 不會影響原始引用
public static void reassignPerson(Person p) {
System.out.println("重新賦值前 - " + p.name);
p = new Person("王五", 40); // 創建新對象,p指向新地址
System.out.println("重新賦值后 - " + p.name);
}
public static void main(String[] args) {
Person person = new Person("張三", 25);
System.out.println("=== 測試修改對象狀態 ===");
System.out.println("調用前: " + person.name + ", " + person.age);
modifyPerson(person); // 傳遞的是對象地址的副本
System.out.println("調用后: " + person.name + ", " + person.age);
// 輸出:李四, 30(原始對象被修改)
System.out.println("\n=== 測試重新賦值引用 ===");
Person person2 = new Person("趙六", 35);
System.out.println("調用前: " + person2.name);
reassignPerson(person2); // 傳遞引用副本
System.out.println("調用后: " + person2.name);
// 輸出:趙六(不變,因為方法內重新賦值不影響原始引用)
}
}
3. 數組傳遞示例
public class ArrayExample {
// 修改數組元素 - 會影響原始數組
public static void modifyArray(int[] arr) {
System.out.println("方法內修改前: " + Arrays.toString(arr));
if (arr.length > 0) {
arr[0] = 100; // 修改數組元素
}
System.out.println("方法內修改后: " + Arrays.toString(arr));
}
// 重新賦值數組引用 - 不會影響原始數組引用
public static void reassignArray(int[] arr) {
System.out.println("重新賦值前: " + Arrays.toString(arr));
arr = new int[]{7, 8, 9}; // 創建新數組
System.out.println("重新賦值后: " + Arrays.toString(arr));
}
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
System.out.println("=== 測試修改數組元素 ===");
System.out.println("調用前: " + Arrays.toString(numbers));
modifyArray(numbers); // 傳遞數組地址的副本
System.out.println("調用后: " + Arrays.toString(numbers));
// 輸出:[100, 2, 3, 4, 5](原始數組被修改)
System.out.println("\n=== 測試重新賦值數組引用 ===");
int[] numbers2 = {10, 20, 30};
System.out.println("調用前: " + Arrays.toString(numbers2));
reassignArray(numbers2);
System.out.println("調用后: " + Arrays.toString(numbers2));
// 輸出:[10, 20, 30](不變)
}
}
4. String特殊示例(不可變對象)
public class StringExample {
// String是不可變對象,任何修改都會創建新對象
public static void modifyString(String str) {
System.out.println("方法內修改前: " + str);
str = str + " World"; // 創建新的String對象
System.out.println("方法內修改后: " + str);
}
public static void main(String[] args) {
String message = "Hello";
System.out.println("調用前: " + message);
modifyString(message); // 傳遞String引用副本
System.out.println("調用后: " + message); // 輸出:Hello(不變)
// 驗證String的不可變性
String s1 = "Java";
String s2 = s1;
s1 = s1 + " Programming"; // s1指向新對象
System.out.println("s1: " + s1); // Java Programming
System.out.println("s2: " + s2); // Java(不變)
}
}
5. 綜合測試類
public class ValuePassingTest {
// 基本類型參數
public static void testPrimitive(int a, double b, boolean c) {
a = 100;
b = 200.5;
c = false;
System.out.println("方法內 - a=" + a + ", b=" + b + ", c=" + c);
}
// 引用類型參數
public static void testReference(List<String> list, StringBuilder builder) {
list.add("新元素"); // 修改列表內容
builder.append("追加內容"); // 修改StringBuilder內容
System.out.println("方法內 - list: " + list);
System.out.println("方法內 - builder: " + builder);
}
public static void main(String[] args) {
// 測試基本類型
int x = 10;
double y = 20.5;
boolean z = true;
System.out.println("=== 基本類型測試 ===");
System.out.println("調用前 - x=" + x + ", y=" + y + ", z=" + z);
testPrimitive(x, y, z);
System.out.println("調用后 - x=" + x + ", y=" + y + ", z=" + z);
// 測試引用類型
System.out.println("\n=== 引用類型測試 ===");
List<String> stringList = new ArrayList<>(Arrays.asList("A", "B", "C"));
StringBuilder stringBuilder = new StringBuilder("原始內容");
System.out.println("調用前 - list: " + stringList);
System.out.println("調用前 - builder: " + stringBuilder);
testReference(stringList, stringBuilder);
System.out.println("調用后 - list: " + stringList); // 被修改
System.out.println("調用后 - builder: " + stringBuilder); // 被修改
}
}
輸出結果示例
=== 基本類型測試 ===
調用前 - x=10, y=20.5, z=true
方法內 - a=100, b=200.5, c=false
調用后 - x=10, y=20.5, z=true
=== 引用類型測試 ===
調用前 - list: [A, B, C]
調用前 - builder: 原始內容
方法內 - list: [A, B, C, 新元素]
方法內 - builder: 原始內容追加內容
調用后 - list: [A, B, C, 新元素]
調用后 - builder: 原始內容追加內容
核心要點總結
- 基本數據類型:傳遞數值副本,方法內修改不影響原始變量
- 引用數據類型:傳遞地址副本,方法內修改對象內容會影響原始對象
- 重新賦值引用:方法內重新賦值引用變量不會影響原始引用
- String特殊性:作為不可變對象,任何修改都會創建新對象
這些案例清晰地展示了Java值傳遞機制的特點,幫助理解方法參數傳遞的本質。

浙公網安備 33010602011771號