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号