java整型比较大小使用“==”引发的血案

目录

背景

原因(方法使用错误)

代码

原码解析

建议


背景

      某个开发小哥哥开发了一段代码,比较2个Long类型的,用了符号“==”;开发自己测试后移交给测试在不同的环境测试后无问题,然后上线;刚上线生产大量报错,代码回滚,然后开始抓鬼.........
 

原因(方法使用错误)

       造成以上问题且多方测试均未发现问题的原因主要是:
       ① 使用基本类型的包装类隐式定义变量 (例如:Integer a = 5;)
       ② 使用比较符==比价变量大小  
       ③ 测试数值范围小,且在【-128~127】区间
 
        总的来讲还是对基本数据类型比较大小的使用方法的不规范(==比价的是物理地址)
Byte、Short、Integer、Long隐式定义变量时;例如:Integer a = 8,会使用Integer的“public static Integer valueOf(int i)”方法完成基本数据类型的装箱,然而......
  • 为了空间和时间的性能,此方法会对经常请求的值【-128~127】缓存到IntegerCache;
  •  不同的对用如果定义的变量相同且均大小在缓存的区间时,对象的引用地址指向了同一个缓存即具备同一个物理地址;
  • “==”比较的是2个对象的内存地址是否相等;当测试数据太小在缓存区间时,用“==”比较结果相等,造成一定的假象;
 

代码

@Test
public void testIntCache() {
 
Integer a1 = -128;
Integer b1 = -128;
log.info("比较结果1:{}", a1 == b1);
log.info("比较结果2:{}", Integer.compare(a1, b1));
 
Integer a2 = 127;
Integer b2 = 127;
log.info("比较结果1:{}", a2 == b2);
log.info("比较结果2:{}", Integer.compare(a2, b2));
 
log.info("vvvvvvvvvvvvvvvvvvvvvvvvvvv");
 
Integer a3 = -129;
Integer b3 = -129;
log.info("比较结果1:{}", a3 == b3);
log.info("比较结果2:{}", Integer.compare(a3, b3));
 
Integer a4 = 128;
Integer b4 = 128;
log.info("比较结果1:{}", a4 == b4);
log.info("比较结果2:{}", Integer.compare(a4, b4));
 
log.info("对于包装类Integer定义的整数,[-128~127]区间会有缓冲池,不建议使用==比较大小");
}

 

执行结果(Integer换成Long后执行结果也是如下):

java整型比较大小使用“==”引发的血案

 

原码解析

自动装箱时使用valueof方法(Integer a = 5;)如果变量的值不在[IntegerCache.low  , IntegerCache.high] 则new一个对象,否则从IntegerCache的缓存中获得对象
java整型比较大小使用“==”引发的血案
 
IntegerCache.cache()的方法:①最小值-128,最大值默认为127也可在jvm参数配置 ②首次加载内部类时调用 
 
java整型比较大小使用“==”引发的血案
 

建议

  • 使用包装类的比较方法(Integer.compare(int x, int y))

  • 使用非包装类定义变量(int,long)

  • 包装类转换成基本数据类型后比较(intValue(), longValue()...)