Java值传递还是引用传递

概念

  1. 指针和引用

    首先java中没有指针的概念,但是在c++中是有指针(*)和引用(&)的概念的,不太好区分,但是以swap方法为例的话,两者都可以达到交换的目的。为了更好的区分我先设定

    指针:直接指向了数据,所有的修改都是直接对数据的修改(但其实指针也是一个对象,里面的值存放了数据的地址)

    引用:通过一个中间引用变量对数据进行了修改,可以通过中间变量间接的修改数据值

  2. 值传递和引用传递

    一直以来我认为的值传递和引用传递都是通过大学课上的swap函数为基础的,所以我认为

    值传递:实参和形参无关联,可以类比一个方法中两个变量,只是值一样

    引用传递:实参和形参有关联,可以类比一个方法中两个变量指向同一个对象,只是引用名不一样,但是引用值是同一个地址

例子

  1. 值传递
public class Test {
    public static void main(String[] args) {
        int val = 20;
        Test.test(val);
        System.out.println("实参:" + val);
    }

    private static void test(int val) {
        val = 10;
        System.out.println("形参:" + val);
    }
}

对于基础变量,实参和形参无关联,互补影响,所以输出为

形参:10
实参:20

  1. 引用传递
public class Test {
    public static void main(String[] args) {
        Stu stu = new Stu();
        stu.setAge(20);
        stu.setName("test");
        Test.test(stu);
        System.out.println("实参:" + stu);
    }

    private static void test(Stu stu) {
        stu.setName("test2");
        stu.setAge(10);
        System.out.println("形参:" + stu);
    }
}

class Stu {
    String name;
    int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

Stu是一个对象,因为引用传递的原因,所以形参和实参指向了同一个地址,如果通过形参对数据进行修改,那么实参指向的数据也会发生改变,因为指向了同一个地址,所以输出

形参:Stu{name='test2', age=10}
实参:Stu{name='test2', age=10}

  1. 引用传递
public class Test {
    public static void main(String[] args) {
        Stu stu = new Stu();
        stu.setAge(20);
        stu.setName("test");
        Test.test(stu);
        System.out.println("实参:" + stu);
    }

    private static void test(Stu stu) {
        stu = new Stu();
        stu.setName("test2");
        stu.setAge(10);
        System.out.println("形参:" + stu);
    }
}

class Stu {
    String name;
    int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

同样的代码,只是比上面多了一行stu = new Stu(); 但此时修改了形参的指向,这里修改的是形参,并未对数据进行修改,修改完后的形参指向了新的地址,从而与实参关联断开,所以结果为

形参:Stu{name='test2', age=10}
实参:Stu{name='test', age=20}

  1. 引用传递
public class Test {
    public static void main(String[] args) {
        String val = "20";
        Test.test(val);
        System.out.println("实参:" + val);
    }

    private static void test(String val) {
        val = "10";
        System.out.println("形参:" + val);
    }
}

对于String这个对象,因为是被final修饰的,所以不管任何改变了数据的操作都是在String池子里新建一个,这里因为没有用new,所以都是指向的String常量池,而且一个指向了"10",一个指向了“20”

结论

从上面的3和4的例子我们看到如果在方法中对引用类型形参进行了“=”这个操作,那么与实参就脱离了连接,形参就不会发生任何改变,所以要注意。

所以我的结论就是基本类型值传递,对象类型引用传递。我在网上看到很多说是值传递,其实说的也有道理,但是每个人有自己的理解,能解决生产中的问题就行。

猜你喜欢

转载自www.cnblogs.com/colin-xun/p/12656773.html