java Integer/Long等比较须知
在java编程中,自动装箱和拆箱,相信大家都不陌生,但是在比较过程中,会有一些坑,尤其是业务代码复杂的时候,比较容易掉进去。今天就说一下,我遇到的一个基本类型比较的问题。
WrapperClass缓存
在基本类型的wrapperClass中,有些是有缓存的,比如Integer。
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() { } }
以上为Integer的缓存,可以看到对于-128到127的Integer在java运行的时候已经作为trust类被加载到jvm中,当然他的IntegerCache类也被初始化完成。
valueOf&intValue
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
这是自动装箱的使用方法,大家可以自己编写一个自动装箱的测试代码,然后通过javap -c命令查看的反编译代码。看到装箱的过程中,使用了IntegerCache中缓存好的Integer。
public int intValue() { return value; }
自动拆箱方法
new
Integer的new方法和其他对象没什么区别。肯定需要开辟新的对象空间。一个新的对象。
小结
通过以上,我们可以看到Integer的装箱和拆箱的原理,然后我们平时使用到的比较的时候就需要注意。
- 如果都是通过自动装箱获得的Integer,如果都在[-127,128]中,那么直接对比的是cache中的对象的引用,也可以间接的达到比较值的作用。
- 如果Integer的值在[-127,128]这个范围外部,那么执行new Integer(i)方法,创建新的对象。==号的作用,失去了间接比对的作用。
综上所述:如果碰到了WrapperClass比较的情况,直接使用CompareTo方法比较。使用==虽然在小值可以间接达到自己的目的,但是很容易掉进这个坑。排查比较困难。
当然除了Integer还有其他的WrapperClass也使用了Cache,如下: