关于Long的==比较的一个大坑

1,110 阅读1分钟

最近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);
}

程序运行结果
image.png

我以为大家经过了Integer的缓存的坑之后,不会再落入Long的坑,

接下里我就分析下这个问题\

  1. 首先看到给Long赋值,字节码是做了调用哪个Long的valueOf自动装箱, image.png
  2. Long的valueOf方法,可以看到会判断参数在-128到127范围,则返回LongCache缓存的值,不在这个范围之外则创建一个新的对象, image.png
  3. LongCache在初始化时初始化一个-128到127范围的缓存放到cache的Long数组中. image.png 看到这里问题原因就清晰了
    为什么例子第一个匹配结果是true? 是因为120属于LongCache范围,所以走缓存,两个对象都是返回缓存的对象,所以两个对象地址是相等的\

为什么例子第二个匹配结果是true? 是因为130属于LongCache范围,所以没走缓存,而是重新new两个Long对象,这两个对象在堆中地址可是不一样的,所以两个对象地址是不相等的 \

总结
今天这个虽说是个小问题,但是也是写代码经常容易忽视的问题,仅供大家吸取经验教训,希望下次不要出现同样的错误。