目录
起因
在阅读《阿里巴巴开发手册》时发现了一句话:
【强制】 所有整型包装类对象之间值的比较, 全部使用equals方法比较。
说明:对于Integer var = ?在-128至127之间的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。
探究
public static Integer valueOf(String s) throws NumberFormatException { public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } |
通过代码我们可以看到valueOf(String)最终调用的是valueOf(int)方法;
在valueOf(int)方法中则是调用IntegerCache.cache[],而这个[]则是数组的标志,难道是从数组里获取数据吗?
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() {} } |
就是当JVM属性java.lang.Integer.IntegerCache.high为空的时候,则定义2个极限值:最小值-128,最大值127;
然后定义一个Integer[]数组,数组长度为128 + 127 +1=256,然后通过一个for循环,从数组下标0开始,从-128依次递增,即
Integer[0]=-128
Integer[1]=-127
Integer[2]=-126
...............
Integer[255]=127
总结
如果Integer的数值是在-128 ~ 127这个区间,那么有很大可可能性是复用Integer[]里的内容,因此,建议使用equels来判断,而不是用==来判断;
扩展
对于Long类、Short类,JDK同样做了缓存操作,区别在于他们不能调整high值,后续再遇到包装类的时候,要注意下,最好看一下源码;