由一个bug引出java包装类型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由一个bug引出java包装类型相关的知识,希望对你有一定的参考价值。
工作中遇到过一个bug,用两个POJO的 Integer 字段 做 == 判断,明明“数值”相等结果返回 false。检查代码,调试,看源码搞了好久,才知道是Java包装类理解不够惹的祸。
为了弄清楚其中的本质,先上一段代码:
1 int a = 5;
2 Integer b = 5;
3 Integer c = Integer.valueOf(5);
4 Integer d = Integer.valueOf(5);
5 Integer e = new Integer(5);
6
7 System.out.println("测试1,a == b 的结果:" + (a == b));
8 System.out.println("测试2,b == c 的结果:" + (b == c));
9 System.out.println("测试3,c == d 的结果:" + (c == d));
10 System.out.println("测试4,d == e 的结果:" + (d == e));
11 System.out.println("测试5,b == e 的结果:" + (b == e));
分析运行结果:测试1说明,一个“数值”与Integer 做==判断,Integer对象会进行自动拆箱然后再进行判断。测试2、3说明,b、c、d 这三个对象内存地址一样,其实是同一个对象。 测试4说明,b 与 e不是同一个对象,且两个 Integer 做 == 判断时不会进行自动拆箱操作。
进一步查看编译后的代码:
发现 其实 b、c、d 都是通过 Integer.valueOf()方法创建的。a、b 比较时进行了拆箱操作。
更进一步查看Integer类的源代码:
哦,原来是Integer内部维护一个对象池,默认值的范围 [-128,127]。(可以通过修改 -XX:AutoBoxCacheMax=<size> 设置缓存的大小,值的范围 [-128,x],low 参数不可修改)。
接来对比一下 new Integer()方法:
直接创建,难怪b 与 e 不是同一个对象。
Java 有八种基本类型,相应的就有八种包装类。既然Integer有缓存,那么其他类型有没有呢?还是来查看源码吧。(JDK版本 1.8.0_05)
Long:
Short:
Byte:
Float:
Double:
Boolean:
Character:
Java的八个包装类,除Float,Double 外其他六个类都在内部维护一个对象池,像上面直接在代码中赋值,编译器后实际上是调用 valueOf(),先去缓存中查找,没有才会创建,减少对象的创建。包装类的对象与基本类型比较会自动拆箱,而对方也是同一个包装类的对象则和普通对象一样。
分析这些有什么用呢?在Java中数据很多情况下用的是包装类型,当要进行比较时两方都是包装类,就会有可能得到诸如“为什么明明两个值一样就是不相等呢?”这样的结果。其他人怎么做我不知道,但是从上一次bug以后,代码中出现包装类比较,只要一方不是基本类型我就把包装拆箱。
以上是关于由一个bug引出java包装类型的主要内容,如果未能解决你的问题,请参考以下文章