2.Java值传递、引用传递问题

Java值传递、引用传递问题

1.值传递

在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。值传递传递的是真实内容的一个副本,对副本的操作不影响原内容,也就是形参怎么变化,不会影响实参对应的内容。

public class T1 {
    public static void main(String[] args) {
        int age = 25;
        float weight = 77.5f;
        Test(age, weight);
        System.out.println("方法执行后的age:" + age);
    }

    public static void Test(int a, float w) {
        System.out.println("传入的age:" + a);
        System.out.println("传入的weight:" + w);
        a = 33;
        w = 89.5f;
        System.out.println("方法内重新赋值后的age:" + a);
        System.out.println("方法内重新赋值后的weight:" + w );
    }
}
执行结果:
传入的age:25
传入的weight:77.5
方法内重新赋值后的age:33
方法内重新赋值后的weight:89.5
方法执行后的age:25
也就是说,age和weight的改动,只是改变了当前栈帧(valueCrossTest方法所在栈帧)里的内容,当方法执行结束之后,这些局部变量都会被销毁,mian方法所在栈帧重新回到栈顶,成为当前栈帧,再次输出a和w时,依然是初始化时的内容。
因此:值传递传递的是真实内容的一个副本,对副本的操作不影响原内容,也就是形参怎么变化,不会影响实参对应的内容。

2.引用传递

”引用”也就是指向真实内容的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向同一块内存地址,对形参的操作会影响到真实内容。
public class T1 {
    public static void main(String[] args) {
        Person p = new Person();
        System.out.println("方法外的地址:" + p);  //Person@7ef20235
        p.setName("无极");
        PersonCrossTest(p);
        System.out.println("方法执行后的name:" + p.getName());
    }

    public static void PersonCrossTest(Person person) {
        System.out.println("方法内的地址:" + person);
        System.out.println("传入的person的name:" + person.getName());
        person.setName("我是李三");
        System.out.println("方法内重新赋值后的name:" + person.getName());
    }
}
执行结果:
方法外的地址:Person@7b23ec81
方法内的地址:Person@7b23ec81
传入的person的name:无极
方法内重新赋值后的name:我是李三
方法执行后的name:我是李三
可以看出,person经过personCrossTest()方法的执行之后,内容发生了改变,这印证了上面所说的 “引用传递” ,对形参的操作,改变了实际对象的内容,但是还没结束!
下面我们对上面的例子稍作修改,加上一行代码:
public class T1 {
    public static void main(String[] args) {
        Person p = new Person();
        System.out.println("方法外的地址:" + p);
        p.setName("无极");
        PersonCrossTest(p);
        System.out.println("方法执行后的name:" + p.getName());
    }

    public static void PersonCrossTest(Person person) {
        System.out.println("方法内传进来的地址:" + person);
        System.out.println("传入的person的name:" + person.getName());
        person = new Person();
        System.out.println("方法内重新赋值的地址:" + person);
        person.setName("李三");
        System.out.println("方法内重新赋值后的name:" + person.getName());
    }
}
java执行结果:
方法外的地址:Person@7b23ec81
方法内传进来的地址:Person@7b23ec81
传入的person的name:无极
方法内重新赋值的地址:Person@6acbcfc0
方法内重新赋值后的name:李三
方法执行后的name:无极
JVM需要在堆内另外开辟一块内存来存储new Person(),地址为“Person@6acbcfc0”,那此时形参person指向了这个地址,假如真的是引用传递,那么由上面讲到: 引用传递中形参实参指向同一个对象,形参的操作会改变实参对象的改变 。可以推出:实参也应该指向了新创建的person对象的地址,所以在执行PersonCrossTest()结束之后,最终输出的应该是后面创建的对象内容。然而实际上,最终的输出结果却跟我们推测的不一样,最终输出的仍然是一开始创建的对象的内容。p依旧是指向旧的对象,person指向新对象的地址。所以此时 对person的操作,实际上是对新对象的操作,于实参p中对应的对象毫无关系
由此可见: 引用传递,在Java中并不存在。

总结

java中只有值传递,基本类型传递的是值的副本,引用类型传递的是引用的副本。
只是在传递过程中:如果是对基本数据类型的数据进行操作,由于原始内容和副本都是存储实际值,并且是在不同的栈区,因此形参的操作,不影响原始内容。如果是对引用类型的数据进行操作,分两种情况,一种是形参和实参保持指向同一个对象地址,则形参的操作,会影响实参指向的对象的内容。一种是形参被改动指向新的对象地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。
参考博文

https://blog.csdn.net/qq_43171869/article/details/83349282?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162116707716780269830210%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=162116707716780269830210&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-83349282.first_rank_v2_pc_rank_v29&utm_term=java%E5%80%BC%E4%BC%A0%E9%80%92%E5%92%8C%E5%BC%95%E7%94%A8%E4%BC%A0%E9%80%92

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值