先抛出两段有意思的代码:

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)的值已经对调了

如果不注意很危险(影响到其他程序的逻辑)

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄