当前位置:网站首页>一个对象引用的思考
一个对象引用的思考
2022-08-04 05:03:00 【jvm77625】
一个有趣且令人困惑的代码片段
Code A:
final ConcurrentHashMap<String, Ref> REFS_MAPS = new ConcurrentHashMap<String, Ref>();
public void put(String key) {
Ref ref = new Ref(key, "1");
ref = new Ref(key, "2");
REFS_MAPS.put(key, ref);
}
public Ref get(String key) {
return REFS_MAPS.get(key);
}
它有可能会得到"1"吗?
错误的解释
在多线程调度的情况下,相同的 key 多次同时调用 put 和 get 方法,从 REFS_MAPS 方法 get 时,正好 put 运行到 Ref ref = new Ref(key, "1"),所以就得到了“1”的值,如下所示:

这个解释是错误的,不会得到“1”。
REFS_MAPS 的 hash Node 存储指向 “ref” 对象的值,而不是对象引用。因此,当 ref 在 put()方法时,ref 的 val 先指向堆中的“1”,后指向堆中的“2”,如下所示:

常见的困惑问题
将 put 方法改一下:
Code B:
public void put(String key) {
Ref ref = new Ref(key, "1");
REFS_MAPS.put(key, ref);
ref = new Ref(key, "2");
}
它有可能会得到"1"吗?
一定会是“1”,虽然 ref 的指向堆中的“2”,但是 REFS_MAPS 的 hash Node 存储指向 “ref” 对象的值还是“1”。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

再将 put 方法改一下:
Code C:
public void put(String key) {
Ref ref = new Ref(key, "1");
REFS_MAPS.put(key, ref);
ref.setValue("2");
}
它有可能会得到"1"吗?
不会的得到“1”,因为 ref 和 REFS_MAPS 存储的 “ref” 对象只指向的同一个值,当 ref 修改了值,REFS_MAPS 中 ref 的值也被修改了。

代码背后真正的意义是什么?
我们知道,值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,而 Java 只有值传递。
在 Code B 中,ref = new Ref(key, "2") 会重新开辟一片内存空间,赋值给 ref,后面的任何修改都不会改变 Ref ref = new Ref(key, "1") 的内容,这里不是引用传递,如果是引用传递的话,REFS_MAPS 中的引用也应该会改变,但是实际上并没有。
在 Code C 中,ref.setValue("2") 影响了 REFS_MAPS 中的值,因为这里是把 ref 的引用的地址复制了一份,传递给了 REFS_MAPS。所以,ref 其实是值传递,把 ref 对象引用的地址当做值传递给了 REFS_MAPS。
所以,值传递和引用传递的区别并不是传递的内容。而是实参到底有没有被复制一份给形参。
边栏推荐
- Get the selected content of the radio box
- C Expert Programming Chapter 5 Thinking about Linking 5.1 Libraries, Linking and Loading
- 系统设计.如何设计一个秒杀系统(完整版 转)
- drools from download to postman request success
- 符号表
- 深度学习21天——卷积神经网络(CNN):实现mnist手写数字识别(第1天)
- Structure function exercise
- JVM Notes
- See how DevExpress enriches chart styles and how it empowers fund companies to innovate their business
- [Cocos 3.5.2]开启模型合批
猜你喜欢
随机推荐
7-3 LVS+Keepalived Cluster Description and Deployment
C专家编程 第5章 对链接的思考 5.6 轻松一下---看看谁在说话:挑战Turning测验
附加:对于“与数据表对应的实体类“,【面对MongoDB时,使用的@Id等注解】和【以前面对MySQL时,使用的@Id等注解】,是不同的;
share总结
文件内容的操作
day13--postman接口测试
[Skill] Using Sentinel to achieve priority processing of requests
C专家编程 第5章 对链接的思考 5.1 函数库、链接和载入
Interesting Kotlin 0x0E: DeepRecursiveFunction
离线采集怎么看sql执行计划
manipulation of file contents
C专家编程 第5章 对链接的思考 5.4 警惕Interpositioning
How to keep the source code confidential in the development under the burning scenario
使用Patroni回调脚本绑定VIP的坑
使用Loadrunner进行性能测试
看DevExpress丰富图表样式,如何为基金公司业务创新赋能
SVM介绍以及实战
编程大杂烩(三)
The symbol table
2022软件测试面试题 最新字节跳动50道真题面试题 刷完已拿下15k 附讲解+答疑









