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

程序运行成果

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

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

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

  1. 首先看到给Long赋值字节码是做了调用哪个Long的valueOf自动装箱,
    关于Long的==比较的一个大坑
  2. Long的valueOf办法,能够看到会判别参数在-128到127范围,则回来LongCache缓存的值,不在这个范围之外则创建一个新的目标,
    关于Long的==比较的一个大坑
  3. LongCache在初始化时初始化一个-128到127范围的缓存放到cache的Long数组中.
    关于Long的==比较的一个大坑
    看到这里问题原因就清晰了
    为什么比如第一个匹配成果是true? 是因为120归于LongCache范围,所以走缓存,两个目标都是回来缓存的目标,所以两个目标地址是持平的\

为什么比如第二个匹配成果是true? 是因为130归于LongCache范围,所以没走缓存,而是重新new两个Long目标,这两个目标在堆中地址可是不一样的,所以两个目标地址是不持平的 \

总结
今日这个虽说是个小问题,但是也是写代码常常简单忽视的问题,仅供我们汲取经验教训,希望下次不要出现相同的错误。