目录
前言
今天逛论坛,遇到一个新手问引用传递的问题,特此记录。
问题是什么
我们先看一下遇到的问题是什么
User类只有一个属性
public static void main(String[] args) { User user1 = new User(); getUser(user1); System.out.println(user1); } private static void getUser(User user2) { User user3 = new User(); user3.setName("a"); user2 = user3; }
那么大家看看输出的结果中user1的name是空还是a呢?
到这里如果您知道为什么的话就不需要花费宝贵的时间往下看了
如果您和我有一样的疑问的话,请往下看,我们先不急着给出答案,来分析下值传递和引用传递
值传递
这里简单介绍一下值传递的原理,已经了解的可忽略看下面
public static void main(String[] args) { int x = 1; getNum(x); System.out.println(x); } private static void getNum(int y) { y = 2; }
这里显而易见x输出的值是1,那么怎么用jvm的变化来解释呢?
以下为内存图解:
引用传递
public static void main(String[] args) { User user1 = new User(); getUser(user1); System.out.println(user1); } private static void getUser(User user2) { user2.setName("a"); }
在这种情况下明显user1的name变成了a
以下为内存图解:
在Java中,新创建的实体对象在堆内存中开辟空间,而引用变量在栈内存中开辟空间
其中的@123为对象在堆中的地址,这里给随机值演示,并不真实是这个样子
其实引用传递本质上也是值传递,不过这个之传递的是引用对象的地址值。
最后,该看看我们最开始的问题出现在什么地方了
如果上面的引用传递你已经看懂的话,仔细考虑考虑也许就会明白了
我们一行一行代码来分析,看jvm做了什么:
User user1 = new User();
第一句执行完后,栈中存储引用地址,堆中存储User实体对象
getUser(user1); getUser(User user2)
第二句执行调用getUser方法时,栈中开辟内存存储user2并将user1存储的地址复制给user2,所有此时user1和user2存储的是同一个地址,也就是指向同一个对象
User user3 = new User(); user3.setName("a");
这里执行就不说了,看图
user2 = user3;
这里就是问题所在,当将user3赋值给user2的时候,是将user3的引用地址赋值给user2,所以user2的地址已经变成了@456,当方法调用完毕,user2和user3都被回收,user1的值始终都没变!
感谢大家阅读,看到这里还不点个赞或者关注么,一起努力,共勉