Hello~各位读者新年好!不知道大家春节假期是否已延长,小黑哥刚接到通知,假期延长到 2 月 2 号,另外回去之后需要在家办公,自行隔离两周。还没试过在家办公,小黑哥就怕到时候生物钟还没调整过来,一觉睡醒已经是下午了。。。

前言

春节假期,还躺在床上小黑哥,收到对账系统的一条预警短信,提示当前系统资金核对存在问题。关于资金的问题,都是大问题,小黑哥连忙拔出电脑,连上 VPN,登录生产环境的查看相关日志。

通过日志,很快小黑哥定位到相关代码。

有的同学可能一下子就能看出这里的问题, Long 对象采用 !=进行比较,这真是一个低级 Bug。幸好 Leader 还不知道,赶紧悄悄修复一下。

现在回想小黑哥当初写这段代码的时候,误以为两个 Long 对象比较将会进行自动拆箱,转变为两个基本数值类型比较。

下面开始复习一下 Java 自动装箱与拆箱机制。

自动装箱与拆箱机制

自动装箱(Autoboxing),是 JDK5 新增的一种语法糖,将会在代码编译时自动将原始类型转换为其对应的对象包装器类。例如将 int 转换为 Integerdouble 转换为 Double。如果转换结果相反,我们就将其称为拆箱。

下面是一个自动装箱的例子:

上面代码 li.add(i) 就发生自动装箱,将基本数据类型 long 转换为其包装类 Long

查看这段代码对应的字节码。

图上黄线标注的字节码对应的代码为 li.add(i)。从这我们可以看到 long 类型的自动装箱实际上调用 Long#valueOf 方法。所以编译器运行时将之前的代码转换为下面的代码

接下来我们来看一个自动拆箱的例子:

由于 Long 包装类对象不能用于求模(%)以及 =,所以这段代码将会发生自动拆箱,将 Long 转化为 long 类型。相应的这里我们也看下其编译之后的字节码。

这里的字节码比之前的复杂很多,这里主要关注黄线部分。可以看到这里调用 Long#longValueLong 对象转为 long 类型。所以自动拆箱这个例子,最后编译器生成字节码等同于以下代码:

Java 规定的 8 种数据类型都有其对应包装类,这些都可以进行相应的自动装箱和拆箱。

这里小结一下:

  1. 自动装箱机制是通过调用包装器类 valueOf 实现
  2. 自动拆箱机制通过调用包装器类的相应的 **Value ,如 longValue, intValue 实现

Cache 陷阱

自动装箱和拆箱概念说起其实挺简单的,但是如果使用不当可能就会踩坑。

我们来看一段代码:

如果你对上面的结果的不是很清楚,恭喜你,暖男小黑哥帮你排雷了。

上面输出结果为:

true
false

这里输出结果之所以为这样,主要与 LongCache 有关。自动装箱进制将会调用 Long#valueOf,其源码如下:

只要数值范围位于 [-128,127] 之间,valueOf 就会返回 LongCache.cache 这个数组中的值。所以 aLong/bLong其实是同一个对象,cLong/dLong 是两个不用对象的。

Long#valueOf 这个方法通过 Cache 减少创建对象的数量,提高相应的空间以及时间性能。

至于为什么缓存 [-128,127] 之间的数字,而没有缓存更多的值,甚至缓存所有的值?

这是因为 Long 范围为**[-263,263]**,总共 2^64 ,这么多对象实例,显然不宜全部缓存。至于 [-128,127] 之间数字 JDK 设计者认为这些数字使用频率高,个人认为这是一个经验值。

另外这个 cache可能会导致另外一个问题:锁共用。

上面代码看起来 A 类使用 along 这个对象锁,而 B 类使用 blong 这个对象锁,看起来两个风马牛不相及,但是实际上两个对象由于 Cache 机制,导致其实际上使用同一个对象,AB 共用同一把锁。

除了 Long#valueOf 方法中存在 Cache 以外,ByteShortIntegerCharacter 也存在相应的 Cache 值。其中 Integer 对象可以通过 -XX:AutoBoxCacheMax=<size> 改变 Cache 初始范围。

技术总结

通过自动装箱与拆箱机制,大大减少了数据类型转化的代码,但是同时带来一些隐藏的问题。这里我们需要记住:

  1. 所有对象之间不能使用 == 比较,需要使用 equals 代替,推荐使用 JDK7 提供的 Objects#equals 方法,该方法可以有效避免比较过程空指针问题
  2. 基本数据类型的包装类不适合当做锁对象

各位读者朋友们,请牢记这两个总结,不要踩中这两个坑哦。另外推荐大家安装一下 FindBugs 这个插件,通过这个插件扫描代码,可以找出代码中的相关缺陷。上面两个问题,通过 FindBugs都能扫描出来,简直神器。

对象比较问题:

锁问题

帮助文档

  1. Autoboxing and Unboxing『https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html』
  2. 极客时间-『Java并发编程实战』专栏

欢迎关注我的公众号:程序通事,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

Leader:这样的 Bug 你也写的出来???相关推荐

  1. 【程序人生】改不完的bug,写不完的需求,爬不完的坑

    给自己多点鼓励,多点自信 !猿前程一帆风顺~ --至在攻城狮道路上一路坎坷的自己

  2. 泡着枸杞写bug的三流程序员凭什么逆袭到一线大厂?

    大多数互联网的从业者都有一个梦想:进大厂. 因为不仅可以享受较好的福利待遇,也能与更优秀的人一起共事,获得更专业.更快速的成长. 最近经常有朋友提及想要入门编程学习,该如何学习? 关于编程学习,各种语 ...

  3. python闯关训练营怎么样3.0_泡着枸杞写bug的三流程序员凭什么逆袭到一线大厂?...

    大多数互联网的从业者都有一个梦想:进大厂. 因为不仅可以享受较好的福利待遇,也能与更优秀的人一起共事,获得更专业.更快速的成长. 最近经常有朋友提及想要入门编程学习,该如何学习? 关于编程学习,各种语 ...

  4. 泡着枸杞写bug的三流程序员凭什么逆袭到一线大厂?你不服不行!

    最近经常有朋友提及,想要入门深度学习,该如何学习? 关于深度学习,网上的资料很多,不过貌似大部分都不太适合初学者. 我曾经是一名三流程序员,每天的工作内容就是在前人留下的 bug 上写新的bug,我以 ...

  5. 谷歌神秘项目曝光!能写代码还会改bug的AI,让码农瑟瑟发抖

    [导读]谷歌神秘项目Pitchfork曝光!这次,会有多少码农被迭代? 做一个程序员,压力有多大? 反正,最近的一个传闻,是让码农们瑟瑟发抖. 传说谷歌正在研发一个秘密的新项目,教AI写代码. 据说, ...

  6. 爆火的ChatGPT太强了!写代码、改bug,网友:可取代Stack Overflow了

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 每天 14:00 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java ...

  7. 爆火的ChatGPT太强了,写代码、改bug,网友:可取代Stack Overflow了

    关于 AI 的问题,可以直接问 AI. OpenAI 新上线的 ChatGPT 可谓是火爆出圈,这个对话模型可以回答后续问题,承认错误,挑战不正确的前提,还能帮你修改代码中的 bug-- 只要和它聊上 ...

  8. 爆火的 ChatGPT 太强了!写代码、改 bug,网友:可取代 Stack Overflow 了

    OpenAI 新上线的 ChatGPT 可谓是火爆出圈,这个对话模型可以回答后续问题,承认错误,挑战不正确的前提,还能帮你修改代码中的 bug-- 只要和它聊上几句,一会儿功夫它就能把问题给你解决了. ...

  9. 做一名开源社区的扫地僧——从Bug report到Google Summer of Code(GSoC):从200个bug到5000美金

    今年的软件自由日(SFD),我在广州Linux用户组的线下活动上做了一个分享,主题叫做<做一名开源社区的扫地僧(上)>.我把演讲的内容重新整理扩充, 写出了文字版, 希望可以跟更多朋友分享 ...

  10. 写给在校生——听师兄传的IT之道

    在担任班主任工作四年之后,我的08级学生离校了.为了收集同学们对我的工作的客观评价,以及能够让他们为我今后的工作提供参考,在选择他们离开之际为我提供信息.有位同学热情地写来了邮件,他谈了一些很好的建议 ...

最新文章

  1. 【git效率篇】在window上面的git bash 配置永久别名 快捷方式
  2. 金山云html文件,金山云安全开放平台
  3. linux libvpx编译安装,linux编译安装时常见错误解决办法
  4. ionic4集成高德地图踩坑(二)
  5. devc++源文件未编译_iOS 编译知识小结
  6. mysql gis 时间_MySQL interval()函数
  7. 生成树协议计算机网络,【图片】生成树协议奇怪!我错哪了两边都绿了呀【计算机网络吧】_百度贴吧...
  8. 30天敏捷结果(14):要事第一
  9. 医用计算机考试题目,2015年全国计算机应医用能力考试辅导资料.doc
  10. 人肉搜索、人肉语言及人肉程序设计
  11. (2020)最新 java 多线程面试题(其一)
  12. 淘宝双11实时数据分析项目报告
  13. 软件测试 边界值法的实例,边界值分析法实例
  14. 华为OD机考 2022
  15. 使文本框永远失去焦点并且去掉边框
  16. 微信公众平台流量主单日广告收入最高达5万元 羡煞偶们
  17. 美国雅虎大幅改善移动应用开发环境“Blueprint”
  18. Android手机之间不消耗流量互传文件
  19. 飘零网络验证-商业版3和金盾版1.5-研究中
  20. Keepalived+NFS+DRBD

热门文章

  1. Svn常见问题及相关原因
  2. mysql里的数据输入窗口是哪个_WINDOWS下使用Mysql 中碰到的问题记录
  3. linux储存文件格式,linux中的.local文件是什么类型的文件?
  4. springboot 获取yml变量_springboot怎么读取不同yml配置文件
  5. sql 取一个月日期去掉周末的所有日期_LeetCode:SQL
  6. 拓端tecdat:Python集成学习:自己编写构建AdaBoost分类模型可视化决策边界及sklearn包调用比较
  7. powermockito测试私有方法_使用JUnit、AssertJ和Mockito编写单元测试和实践TDD (十)在项目中准备测试环境...
  8. 用oracle的sqlload导入文件到数据库
  9. Java从入门到精通 第10章 方法
  10. python for a,b in c