最近review代码, 发现代码中会使用到Long做主键id,然后判断两个id是否相等使用==, 刚开始程序很正常,数据也都正确返回,后面就发现不对了.
就如下面例子:
public static void main(String[] args) {
Long i = 120L;
Long j = 120L;
System.out.println(i == j);
Long m = 130L;
Long n = 130L;
System.out.println(m == n);
}
程序运行结果
我以为大家经过了Integer的缓存的坑之后,不会再落入Long的坑,
接下里我就分析下这个问题\
- 首先看到给Long赋值,字节码是做了调用哪个Long的valueOf自动装箱,
- Long的valueOf方法,可以看到会判断参数在-128到127范围,则返回LongCache缓存的值,不在这个范围之外则创建一个新的对象,
- LongCache在初始化时初始化一个-128到127范围的缓存放到cache的Long数组中.
看到这里问题原因就清晰了
为什么例子第一个匹配结果是true? 是因为120属于LongCache范围,所以走缓存,两个对象都是返回缓存的对象,所以两个对象地址是相等的\
为什么例子第二个匹配结果是true? 是因为130属于LongCache范围,所以没走缓存,而是重新new两个Long对象,这两个对象在堆中地址可是不一样的,所以两个对象地址是不相等的 \
总结
今天这个虽说是个小问题,但是也是写代码经常容易忽视的问题,仅供大家吸取经验教训,希望下次不要出现同样的错误。