为什么不建议使用“==”来比较两个Integer值?转载本文请联系Java极客技术公众号。众所周知,阿里巴巴开发手册中有一个强制性的规定,说包装对象之间比较值时需要使用equals方法,-128和127之间的值比较可以使用==,如如下图所示。具体原因相信大家都知道。虽然规则中提到可以用==来比较-128和127之间的值,但是阿芬强烈建议大家不要这样做。封装类统一使用equals,尤其是传递一些值时必须注意那些来自API或RPC接口的。我们看下面的程序==0");}else{System.out.println("a!=0");}System.out.println(a==b);System.out.println(a==0);}privatestaticIntegergenA(){returnnewInteger(0);}privatestaticIntegergenB(){return0;}}大家可以先看上面的代码,猜猜运算结果是什么,如果注释掉Integera=genA();这一行整数a=genB();放开这一行,运行的结果是什么。那么,123的结果如下。当我们替换注释行时,运行结果如下。其实很多朋友都知道为什么,因为genA()方法使用了Integer的构造函数,构造的是一个新的对象,所以在使用==进行比较的时候,被比较的两个对象是不一样的。是的,原因是这样的,但是还有一点不清楚,那就是为什么使用genA()时,下面的结果会不一样。System.out.println(a==b);//falseSystem.out.println(a==0);//true其实在短短的几行代码中,有几个知识点,即自动装箱Unboxing并为整数缓存从-128到127的数字。装箱和拆箱:自动将基本数据类型转换为包装类型;拆箱:自动将包装器类型转换为基本数据类型。Integer的valueOf(int)方法在装箱时自动调用。拆箱时会自动调用Integer的intValue方法。在上面的代码中,Integerb=0;将触发自动装箱并调用IntegervalueOf()方法。当使用a==0这句话时,会触发自动拆箱。然后我们查看源码,发现缓存逻辑如下,其中IntegerCache.low为-128,IntegerCache.high默认为127,但可以通过JVM参数配置。我们这里的代码是0,所以会从缓存中获取。publicstaticIntegervalueOf(inti){if(i>=IntegerCache.low&&i<=IntegerCache.high)returnIntegerCache.cache[i+(-IntegerCache.low)];returnnewInteger(i);}为了完整说明Integer的缓存,我们来看在下面段程序的执行结果Integerc1=128;Integerc2=128;System.out.println(c1==c2);运行前我们自己分析一下,首先Integerc1=128和Integerc2=128根据我们上面说的,会触发自动装箱调用valueOf方法。通过valueOf源码可以看出128默认已经不在Integer缓存中了,所以如果不满足条件,会通过newInteger构造方法创建两个对象,所以最终结果应该是输出false.先说说为什么不建议直接用==来实现-128和127的比较,显然和我们上面的genA()方法是一样的。在很多情况下,要知道如何获取方法值并不容易,即使在缓存的范围内,其他的也有可能是通过构造函数创建的,所以我们在做比较的时候,很有可能会和预期的不一样,从而导致意外。尤其是如果通过RPC接口获取返回结果,我们甚至可能根本看不到别人的实现方法,更别提提前知道了。所以我们还是老老实实按照阿里巴巴的Java规范写代码,用equals方法判断,肯定是没问题的。
