Integer
先抛出两段有意思的代码:
1、猜猜下面代码的输出结果是什么:
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。Integer i1 = 80, i2 = 80, i3 = 999, i4 = 999; System.out.println(i1 == i2); System.out.println(i3 == i4);
2、实现swap方法:
public static void main(String[] args) throws Exception { Integer a = 1; Integer b = 2; System.out.println("a=" + a + ",b=" + b); swap(a, b); System.out.println("a=" + a + ",b=" + b); } public static void swap(Integer numa, Integer numb){ //实现代码 }
----------------------------------------------分割线--------------------------------------------------
1、答案:true false
在我们的认知里,如果i1==i2为true的话,那么i3==i4理论上也应该为true,很明显,结果告诉我们:i1和i2是同一个对象,i3和i4是不同对象
为什么会出现这样的结果?我们回到Integer的源码上:
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的内部静态类:IntegerCache,缓存了-128-127的Integer对象。
而Integer i1 = 80,实际上是调用了valueOf(int i)方法,如下:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
此时是不是很清楚了,如果 i 不在[-128,127]的范围,则 new Integer(i),很自然i3=999 和 i4=999不是同一个对象了
2、答案:大部分人一第一感觉会这样想:
public static void swap(Integer numa, Integer numb){ Integer tem = 0; tem = numa; numa = numb; numb = tem; }
乍看没什么问题,但对Java方法是值传递,不是地址传递(啥意思? 就是原对象的copy而已,怎么变都不会影响到原对象),所以上面的方法行不通
既然Java是值传递,那是不是就无法实现swap了? 也不是,可以用以下代码实现,但要注意小心使用(!!!!)
public static void swap(Integer numa, Integer numb) throws Exception{ int tem = numa; Field field = Integer.class.getDeclaredField("value"); field.setAccessible(true); field.setInt(numa, numb); field.setInt(numb, tem); }
代理模式,交换IntegerCache里两个对象的值,结果很完美,也实现了 a 和 b 的交换
但是
但是
但是
System.out.println("Integer.valueOf(1)=" + Integer.valueOf(1)); //结果是2,而不是1
这是什么情况,Integer.valueOf(1)的值都变成了2了。 还记得上面交换IntegerCache里两个对象的值吗,Integer(1)和Integer(2)的值已经对调了
如果不注意很危险(影响到其他程序的逻辑)
