Java 值传递详解
约 814 字大约 3 分钟
Java 值传递详解
形参&实参
- 实参:传递给方法的实际值。
- 形参:方法定义时使用的参数,用来接收实参。
String hello = "Hello!";
sayHello(hello); // hello 为实参
void sayHello(String str) { // str 为形参
System.out.println(str);
}
值传递&引用传递
- 值传递:实参的值被复制给形参,形参是实参的副本,对形参的修改不会影响实参。
- 引用传递:传递的是实参的内存地址,形参和实参指向同一个对象,对形参的修改会影响实参。
在 Java 中,所有传参都是 值传递,即使是引用类型的参数。
为什么 Java 只有值传递?
案例 1:传递基本类型参数
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
swap(num1, num2);
System.out.println("num1 = " + num1); // 输出: num1 = 10
System.out.println("num2 = " + num2); // 输出: num2 = 20
}
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
System.out.println("a = " + a); // 输出: a = 20
System.out.println("b = " + b); // 输出: b = 10
}
输出:
a = 20
b = 10
num1 = 10
num2 = 20
解析:a
和 b
是 num1
和 num2
的副本,修改它们不会影响到原来的 num1
和 num2
。
案例 2:传递引用类型参数
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
System.out.println(arr[0]); // 输出: 1
change(arr);
System.out.println(arr[0]); // 输出: 0
}
public static void change(int[] array) {
array[0] = 0; // 修改数组的第一个元素
}
输出:
1
0
解析:传递的是 arr
数组的地址副本,所以修改 array[0]
会影响到原数组。
案例 3:传递引用类型参数
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
Person xiaoZhang = new Person("小张");
Person xiaoLi = new Person("小李");
swap(xiaoZhang, xiaoLi);
System.out.println("xiaoZhang: " + xiaoZhang.getName()); // 输出: 小张
System.out.println("xiaoLi: " + xiaoLi.getName()); // 输出: 小李
}
public static void swap(Person person1, Person person2) {
Person temp = person1;
person1 = person2;
person2 = temp;
System.out.println("person1: " + person1.getName());
System.out.println("person2: " + person2.getName());
}
输出:
person1: 小李
person2: 小张
xiaoZhang: 小张
xiaoLi: 小李
解析:person1
和 person2
是 xiaoZhang
和 xiaoLi
的地址副本,互换地址不会影响到实参的对象。
引用传递是什么样的?
引用传递在 Java 中并不存在,但可以通过 C++ 的示例理解引用传递的概念。
C++ 示例:
#include <iostream>
void incr(int& num)
{
std::cout << "incr before: " << num << "\n";
num++;
std::cout << "incr after: " << num << "\n";
}
int main()
{
int age = 10;
std::cout << "invoke before: " << age << "\n";
incr(age);
std::cout << "invoke after: " << age << "\n";
}
输出:
invoke before: 10
incr before: 10
incr after: 11
invoke after: 11
C++ 使用 int&
作为参数类型来实现引用传递,传递的是变量的引用。
为什么 Java 不引入引用传递?
- 安全性:值传递确保方法内部的修改不会影响到外部数据,避免了意外的修改。
- 简洁性:Java 设计时强调简洁易用,摒弃了 C++ 中容易导致问题的引用传递特性。
总结
Java 中的所有方法参数传递都是 值传递:
- 基本类型参数:传递的是值的副本。
- 引用类型参数:传递的是引用的副本(即地址值的副本)。
Java 中没有引用传递,虽然引用类型的参数在方法内可以修改对象的状态,但形参本身的引用不会影响到实参。