为什么Java只有值传递?


形参和实参

  • 形参(形式参数,Parameters):用于定义函数/方法,接收实参,不需要有确定值
  • 实参(实际参数,Arguments):用于传递给函数/方法,必须要有确定值
public static void main(String[] args) {
    // str为实参
    String str = "Hello, World!";
    sayHello(str);
}
// string为形参
static void sayHello(String string) {
    System.out.println(string);
}

值传递和引用传递

  • 值传递:方法接收的是实参值的拷贝,会创建副本
  • 引用传递:方法接收的是实参所引用的对象在堆中的地址,不会创建副本,对于形参的修改将影响到实参

交换两个变量的值

@Test
public void testSwap1() {
    int a = 10;
    int b = 20;
    System.out.println("a: " + a + ", b: " + b);
    swap1(a, b);
    System.out.println("a: " + a + ", b: " + b);
}
public void swap1(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

很明显这样子交换是不行的,传入的参数其实是实参的拷贝,所以并不会交换两个参数的值

image-20240423152414860

正确的做法:

int A;
int B;
@Test
public void testSwap2() {
    testStream t = new testStream();
    t.A = 10;
    t.B = 20;
    System.out.println("A: " + t.A + ", B: " + t.B);
    t.swap2(t);
    System.out.println("A: " + t.A + ", B: " + t.B);
}
public void swap2(testStream t) {
    int temp = t.A;
    t.A = t.B;
    t.B = temp;
}

往形参里面传入对量,在交换的时候就是实实在在的交换对象在堆中的地址,所以会发生交换

image-20240423152503778

为什么Java只有值传递?

例1:传递基本类型参数

就是上面提到的交换两个参数值,在swap1()方法中,形参a,b二值进行交换并不会影响到实参a,b二值,只是实参复制的副本,无论副本怎么修改都不会影响到原件本身。

例2:传递引用参数类型(1)

public static void main(String[] args) {
    int[] arr = {1, 2, 3, 4, 5};
    System.out.println(arr[0]);
    change(arr);
    System.out.println(arr[0]);
}
public static void change(int[] array) {
    array[0] = 0;
}

运行结果

1
0

其实这里传递的还是值,只不过这个值是实参的地址

也就是说change方法的参数拷贝的是arr(实参)的地址,因此他和arr指向的是同一个数组对象,这也就说明了为什么方法内部对形参的修改会影响到实参

例3:传递引用参数类型(2)

Person

package com.feliks;

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person(String name) {
        this.name = 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: 小李

可以看到,两个引用类型的形参交换并没有影响到实参,swap 方法的参数 person1person2 只是拷贝的实参 xiaoZhangxiaoLi 的地址。因此, person1person2 的互换只是拷贝的两个地址的互换罢了,并不会影响到实参 xiaoZhangxiaoLi


文章作者: Feliks
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Feliks !
评论
  目录