基本概念
形参和实参
- 形参:在定义方法时,方法名后面括号()中声明的变量称为形式参数,简称形参。
- 实参:在调用方法时,方法名后面括号()中使用的值、变量、表达式都称为实际参数,简称实参。
值传递规则
- 规则:实参给形参赋值的过程
- 如果形参是基本数据类型的变量,则将实参保存的数值赋值给形参
- 如果形参是引用数据类型的变量,则将实参保存的地址赋值给形参
代码案例
1. 基本数据类型传递示例
public class PrimitiveTypeExample {public static void modifyValue(int x) {System.out.println("方法内修改前 - x = " + x); // 输出:10x = 20; // 修改形参的值System.out.println("方法内修改后 - x = " + x); // 输出:20}public static void main(String[] args) {int num = 10;System.out.println("调用方法前 - num = " + num); // 输出:10modifyValue(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 ProgrammingSystem.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值传递机制的特点,帮助理解方法参数传递的本质。