Java之值传递、引用传递

188 阅读5分钟

概念

值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递:指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

误区:通过传递的内容来区分,如果是个值,就是值传递;如果是个引用,就是引用传递。 java 是 引用传递。 传递的参数如果是普通类型,就是值传递;如果是对象就是引用传递。

举个例子

例子1

public class Test {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 20;
        temp(num1, num2);
        System.out.println("main() num1 = " + num1);
        System.out.println("main() num2 = " + num2);
}

public static void temp(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
        System.out.println("temp() a = " + a);
        System.out.println("temp() b = " + b);
}

}

输出结果为:

temp() a = 20
temp() b = 10
main() num1 = 10
main() num2 = 20

为什么temp方法输出的值进行了交换,而main输出的却没交换?

1.对于基本数据类型来说,使用的是值传递。即 temp=a;a=b;b=temp; 这种情况。

2.但在函数方法中,即实参传递给形参这种情况下,首先把实参复制了一份,并复制给形参。也就是得到的形参是实参的备份。

3.通过对复制出来的备份进行值的交换,并不会影响原来的数值。这也就说明了为什么temp方法输出的值进行了交换,而main输出的却没交换

例子2

public class Test {
    public static void main(String[] args) {
            Student t1 = new Student("张三", 18);
            Student t2 = new Student("李四", 19);
            temp(t1, t2);
            System.out.println("main() t1:" + t1);
            System.out.println("main() t2:" + t2);
    }

    private static void temp(Student t1, Student t2) {
            Student t = t1;
            t1 = t2;
            t2 = t;
            System.out.println("temp() t1:" + t1);
            System.out.println("temp() t2:" + t2);
    }
}
class Student {
        String name;
        int age;

    public Student(String name, int age) {
            this.name = name;
            this.age = age;
    }

    @Override
    public String toString() {
            return "Test {" +
                            "name='" + name + '\'' +
                            ", age=" + age +
                            '}';
    }
}

输出结果为:

temp() t1:Test {name='李四', age=19}
temp() t2:Test {name='张三', age=18}
main() t1:Test {name='张三', age=18}
main() t2:Test {name='李四', age=19}

原因同例子1,本例子是将实参的地址复制了一份,并赋值给形参,然后进行交换,使其改变指向。 但是,注意: 这并不是引用传递,在Java里只能叫传递了对象的引用,本质上是传递了对象的引用(地址)的副本,这也算值传递。

若将交换函数改成如下代码,则成功进行交换

public class Test {
    public static void main(String[] args) {
            Student t1 = new Student("张三", 18);
            Student t2 = new Student("李四", 19);
            change(t1,t2);
            System.out.println("main() t1:" + t1);
            System.out.println("main() t2:" + t2);
    }
    private static void change(Student t1, Student t2) {
            Student t = new Student("王五",20);
            t.name=t1.name;
            t.age = t1.age;
            t1.name= t2.name;
            t1.age= t2.age;
            t2.name= t.name;
            t2.age = t.age;

            System.out.println("change() t1:" + t1);
            System.out.println("change() t2:" + t2);
    }

    private static void temp(Student t1, Student t2) {
            Student t = t1;
            t1 = t2;
            t2 = t;
            System.out.println("temp() t1:" + t1);
            System.out.println("temp() t2:" + t2);
    }
}
class Student {
        String name;
        int age;

    public Student(String name, int age) {
            this.name = name;
            this.age = age;
    }

    @Override
    public String toString() {
            return "Test {" +
                            "name='" + name + '\'' +
                            ", age=" + age +
                            '}';
    }
}

输出结果为:

change() t1:Test {name='李四', age=19}
change() t2:Test {name='张三', age=18}
main() t1:Test {name='李四', age=19}
main() t2:Test {name='张三', age=18}

例子3

大家看一下这个例子输出啥呢

class Test{
    static void temp( int[] array ){
        int[] arrayTemp = array;
        arrayTemp[0] = 99;
    }
}

class TestIt{
    public static void main( String[] args ){
        int[] array = {1, 2, 3, 4, 5};
        Test.temp(array);
        for (int i = 0; i < array.length; i++){
            System.out.print(array[i] + " ");
        }
    }
}

输出结果为:

99,2,3,4,5

这是因为传递的参数array和局部变量arrayTemp引用的是同一个数组对象,因此在temp方法中对数组元素的修改也会影响到array数组。所以最终array数组的第一个元素的值被修改为了99。

总结

值传递是指在调用函数时将实际参数复制一份传递到函数中;引用传递是指在调用函数时将实际参数的引用直接传递到函数中。

Java中的基本数据类型是值传递。针对 八种基本数据类型来讲,当以参数形式传递给方法是,会把值copy一个新的变量,供该方法内使用。两个变量互不影响

对于八种基本数据类型的包装类和String 他们是不可变对象 ,所以也会以值传递的形式传进方法内。比如:Integer 类中 有final修饰

很多人却误认为Java中的对象传递是引用传递。之所以会有这个误区,主要是因为Java中的变量和对象之间是有引用关系的。Java语言中是通过对象的引用来操纵对象的。所以,很多人会认为对象的传递是引用的传递。

Java对象的传递,是通过复制的方式把引用关系传递了,如果我们没有改引用关系,而是找到引用的地址,把里面的内容改了,是会对调用方有影响的,因为大家指向的是同一个共享对象。

引用传递:对于引用数据类型,会把对象的引用传入方法内,会相互影响.

引用传参,传的是对象的地址,通过地址访问地址指向的内存空间lian