生产上有一个批量任务,有一天突然不执行了,感觉很怪异,就调查了代码,发现是Integer引起的,具体往下看代码。
Integer引发的生产问题
我们有个Batch的实体类,里面有个Integer的id 成员变量,这个是数据库自增字段,具体代码如下:
batch实体类
一个服务类在执行业务逻辑的时候,会判断传入的id是否和数据库中的Batch的id是否一致,如果一样才执行业务逻辑。具体看看代码:
service服务类
下面做了小测试,发现只有id为1的执行了,128的没有执行,大家都知道== 比较的是对象的内存地址,既然1是相等的,为什么128就不相等了?
其实这里面有两个问题:
1、方法声明是Integer类型,传入一个基本类型怎么也可以?
2,对象的比较==用法问题?
先看第一个问题,第一个问题就是Java 在Java SE5引入的自动装箱和自动拆箱功能。
自动装箱和自动拆箱
装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。基本类型就如:int,char,float,double等,对应的包装类型Interger,Character,Float,Double。
自动装箱和拆箱
我们看看装箱是怎么转换的,先看编译后的代码,我们用javap -c命令。
编译后的代码
我们发现装箱时调用包装类型的valueOf方法,拆箱则调用的是intValue方法。其他包装类也是类似,装箱的方法是valueOf方法,拆箱是xxxValue方法。
第二个问题,为什么Integer的比较可以用==,但是不是所有的值都可以。
Integer的比较
我们知道==比较的对象的内存地址,Integer对象的比较可以用==说明两个对象是同一个。上面也说了,装箱会调用valueOf方法,看看Integer的valueOf方法。
valueOf方法
看到了吧这个方法中有缓存,如果在low和high之间是不会创建新对象的,我们看看填充缓存的代码。
Integer的缓存
从上面的源码看到low为-128和high为127,因此用Integer的valueOf自动装箱或者类型转换时,如果值在[-128,127]之间时,是不会创建对象的,所有==是成立的,如果超过这个范围对象就不是同一个了,用==肯定不成立的。
以上就解释了Integer的比较用==是在一定范围内没问题,可能某一天问题就会出现。所以建议比较对象用equals。
if(Integer == int)
在条件中比如有类似if(Integer == int)的比较,如果包装类型不为null的前提下会转成基本类型再比较,此时会调用对象的xxxValue方法;如果对象为null此时会抛出空指针NullPointerException。
领取专属 10元无门槛券
私享最新 技术干货