Java Integer 类型的数据比较时使用 == 可能存在的问题
测试代码
运行结果
突然我就很难受了 。
下面是在解决问题时的记录。
这里的 gods.getType(); 返回一个Integer类型的变量。
枚举类型 PACKAGE.getCode();也返回一个Integer类型的变量。
Integer 是引用类型,Integer 类型的变量在用 “ == ” 比较时会进行内存地址比较。
疑点1
通过以下代码片段可以得知关于Integer对象内存空间地址的说法,
在自动装箱过程中 Integer 会自动缓存 -128~127范围内的值,所以所有在这个范围内的值相等的Integer对象都会共用一块内存,而不会开辟多个;超出这个范围内的值对应的Integer对象有多少个就开辟多少个内存。
(具体可自行参照源码分析)
测试代码
运行结果
class 反编译代码
(可以看到反编译后的源码中,之前定义的Integer 类型的变量被自动装箱, Integer类型在与 int 类型比较时,被自动拆箱)
所以理论上 我上面的Test 代码都应该输出 true。
== 比较时 我的比较值都是 3,根据自动装箱原则,那么它们应该都是共用一个内存空间地址。
但是输出了 false。 所以继续排查(疑点1排除)
疑点2
仔细阅读代码之后,发现这个goods 对象是从redis缓存中反序列化来,那么是不是反序列化之后的对象 内存地址发生了改变。
然后影响了Integer 的内存地址的变化。
这里介绍一个可以 根据内存地址获取的hash值 的函数。
System.identityHashCode(Object obj);
(每次运行程序时,内存会为对象重新分配内存地址,因此得到的hash值也不一样。)
测试代码: 运行结果:
可以看到 原先没有被序列化过的 goods 对象的 type 属性的内存Hash值 和 枚举常量中的 内存Hash 值是 相等的。
但是将 goods 序列化成 byte 数值 ,然后再反序列化成 goods2 对象。goods2 对象的type 属性的内存Hash值 发生了改变。
所以导致了 3(Integer) == 3 (Integer) 进行对象地址比较时返回 false 的结果。
呀呀呀呀呀。
我真是太菜了。。太菜了。。。太菜了。。。。
关于反序列化和序列化
目前没找到一篇令我满意的 文章 ,先暂且放一篇,等找到更好的再更新吧
参考资料:
- hashCode和identityHashCode
- java中int与Integer用==比较详解
- Java中Integer与int类型的装箱和拆箱
- Java对象的序列化(Object Serialization)
- Java 对象在堆中的内存结构