经过pass方法执行后,实参的值竟然被改变了!!!那按照上面的引用传递的定义,实际参数的值被改变了,这不就是引用传递了么?
有同学可能会说:难道在Java的方法中,在传递基本数据类型的时候是值传递,在传递引用数据类型的时候是引用传递?
其实不然,Java中传递引用数据类型的时候也是值传递 。
为什么呢?
先给大家说一下概念中的重点:
值传递,是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数 。总结下两者的区别:
引用传递,是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数 。
值传递引用传递根本区别会创建副本不会创建副本所以函数中无法改变原始对象函数中可以改变原始对象
敲黑板:复制的是参数的引用(地址值),并不是引用指向的存在于堆内存中的实际对象 。
main方法中的user是一个引用(也就是一个指针),它保存了User对象的地址值,当把user的值赋给pass方法的user形参后,即让pass方法的user形参也保存了这个地址值,即也会引用到堆内存中的User对象 。
上面代码中,之所以产生引用传递的错觉,是因为参数保存的是实际对象的地址值,你改变的只是地址值指向的堆内存中的实际对象,并没有真正改变参数,参数的地址值没有变 。
下面结合生活中的场景,再来深入理解一下值传递和引用传递 。
你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递 。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字 。
你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递 。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙 。
但是,不管上面哪种情况,你的朋友拿着你给他的钥匙,进到你的家里,把你家的电视砸了 。那你说你会不会受到影响?
我们在pass方法中,改变user对象的name属性的值的时候,不就是在“砸电视”么 。你改变的不是那把钥匙(地址值),而是钥匙打开的房子(地址值对应的实际对象) 。
那我们如何真正的改变参数呢,看如下代码:
public class ParamPass3 { public static void main(String[] args) { ParamPass3 p = new ParamPass3();? User user = new User(); user.setName("张三"); user.setAge(18);? System.out.println("pass方法调用前,user= " + user.toString()); p.pass(user); System.out.println("pass方法调用后,user= " + user.toString()); }? public void pass(User user) { user = new User(); user.setName("李四"); user.setAge(20); System.out.println("pass方法中,user = " + user.toString()); }}?class User { /** * 姓名 */ private String name; /** * 年龄 */ private 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 "User{" + "name='" + name + ''' + ", age=" + age + '}'; }}在这段代码中,pass方法中,我们真正的改变了user参数,因为它指向了一个新的地址(user = new User()),即参数的地址值改变了 。运行结果如下:
pass方法调用前,user= User{name='张三', age=18}pass方法中,user = User{name='李四', age=20}pass方法调用后,user= User{name='张三', age=18}从结果看出,对参数进行了修改,没有影响到实际参数 。
所以说,Java中其实还是值传递的,只不过对于引用类型参数,值的内容是对象的引用 。
【深入理解Java中方法的参数传递机制】
推荐阅读
- Java扫码点餐小程序源码 智慧点餐系统源码 点餐小程序 外卖订餐
- 递归与动态规划算法时间复杂度的简单理解
- 仅需 5 分钟,彻底理解 cookie、session、token
- Java 程序员必须掌握的 8 道数据结构面试题,你会几道?
- java架构到底是做什么的,一段对话让你懂
- 简单理解JavaScript,TypeScript和JSX
- HTML、CSS、JavaScript、PHP、 MySQL 的学习顺序是什么?
- 要做到相互理解和包容 人是相互的 婆媳之间
- Java解决高并发秒杀
- Java正确获取客户端真实IP方法整理——附教程