文章目录
在 Java 中,按值传递和按引用传递是两种常见的参数传递方式。为了深入理解这两种传递方式,我们需要从 Java 如何处理方法参数传递来入手。其实,Java 中所有的参数传递都是
按值传递
,但是需要注意的是,对于对象参数,Java 按值传递的是引用的副本。
一、按值传递(Pass by Value)
在 Java 中,所有方法参数的传递方式实际上是 按值传递。这意味着当我们将一个变量传递给方法时,方法接收的是该变量的副本(值),而不是变量本身。
1.1 对于基本数据类型(如 int
, double
, boolean
等)
- 传递的值是基本数据类型的副本。
- 修改方法内部副本的值不会影响原始变量。
示例:基本数据类型按值传递
public class ValuePassing {
public static void main(String[] args) {
int a = 5;
System.out.println("Before method call: a = " + a); // 输出: a = 5
modifyValue(a);
System.out.println("After method call: a = " + a); // 输出: a = 5
}
public static void modifyValue(int num) {
num = 10; // 修改的是 num 的副本,不会影响原始 a
}
}
当我们将
a
传递给modifyValue
方法时,方法接收的是a
的副本。修改num
(副本)不会影响原始变量a
,所以a
的值保持不变。
1.2 对于引用数据类型(如对象)
- 对于对象类型,传递的是对象引用的副本。换句话说,传递的是指向对象内存地址的引用副本,而不是对象本身。
- 修改对象的内容(通过引用副本)会影响原始对象,但如果改变引用的指向,则不会影响原始引用。
示例:引用数据类型按值传递
public class ReferencePassing {
public static void main(String[] args) {
Person p = new Person("John", 30);
System.out.println("Before method call: " + p.getName()); // 输出: John
modifyName(p);
System.out.println("After method call: " + p.getName()); // 输出: Mike
}
public static void modifyName(Person person) {
person.setName("Mike"); // 修改对象的属性,影响原始对象
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
二、按引用传递(Pass by Reference)
- 按引用传递是指方法接受的是对象的引用本身,因此方法可以直接修改原始对象的值。值得注意的是,Java 并不支持按引用传递。
- 在 Java 中,对于对象类型,实际上还是 按值传递,传递的是对象引用的副本,而不是引用本身。因此,我们不能在方法内改变引用的指向(例如指向另一个对象),但可以改变引用指向对象的内容。
三、示例
public class Main {
public static void main(String[] args) {
int a = 3;
int b = 4;
String zhang = "zhangsan";
String li = "lisi";
Peoplek i = new Peoplek();
i.name = "i";
Peoplek j = new Peoplek();
j.name = "j";
test1(a, b);
System.out.println(a + " " + b);
test1(zhang, li);
System.out.println(zhang + " " + li);
test1(i, j);
System.out.println(i.name + " " + j.name);
}
// 重载的 test1 方法,处理基本类型的传递(按值传递)
private static void test1(int a, int b) {
int c = a;
a = b;
b = c;
}
// 重载的 test1 方法,处理字符串的传递(按值传递)
private static void test1(String zhang, String li) {
String a = zhang;
zhang = li;
li = a;
}
// 重载的 test1 方法,处理 Peoplek 对象的传递(传递引用)
private static void test1(Peoplek i, Peoplek j) {
String a = i.getName();
i.name = j.getName();
j.name = a;
}
static class Peoplek {
String name;
public String getName() {
return name;
}
}
}
a
和b
的值在test1(a, b)
中没有改变,因为是按值传递。
zhang
和li
的值在test1(zhang, li)
中没有改变,因为是按值传递(字符串是不可变的)。
i.name
和j.name
的值被互换,因为是传递的对象引用,修改的是对象的内容。
输出:
四、总结
- 按值传递:方法接收到的是传入参数的副本,无论是基本类型的副本还是引用类型的副本。对于基本类型,副本的修改不会影响原始值;对于引用类型,副本的修改会影响原始对象的状态,但无法改变原始引用指向的对象。
- 按引用传递(实际上 Java 不支持): 方法接收的是传入对象的引用本身,可以直接修改原始对象的内容,但不能改变引用本身。