最近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目标,这两个目标在堆中地址可是不一样的,所以两个目标地址是不持平的 \
总结
今日这个虽说是个小问题,但是也是写代码常常简单忽视的问题,仅供我们汲取经验教训,希望下次不要出现相同的错误。