Integer的实现

先看一段代码,猜猜结果是什么?

public class IntegerDemo {
    public static void main(String[] args) {
        Integer a =1, b = 2;
        System.out.println("before, a="+a+",b="+b);
        swap(a,b);
        System.out.println("after, a="+a+",b="+b);
    }

    private static void swap(Integer i1, Integer i2) {
        Integer temp = i1;
        i1 = i2;
        i2 = temp;
    }
}

结果:

before, a=1,b=2
after, a=1,b=2

为什么会这样?图示看下
在这里插入图片描述
i1,i2 的引用的改变,对a,b没有任何影响

再来看,我们想要更改 a 和 b 的值

public class IntegerDemo {
    public static void main(String[] args) {
        Integer a =1, b = 2;//自动装箱 相当于 Integer a = Integer.valueOf(1);
        System.out.println("before, a="+a+",b="+b);
        //swap(a,b);
        change(a,b);
        System.out.println("after, a="+a+",b="+b);
    }


    private static void change(Integer i1, Integer i2) {
        i1 = 4;
        i2 = 5;
    }

    private static void swap(Integer i1, Integer i2) {
        Integer temp = i1;
        i1 = i2;
        i2 = temp;
    }
}

结果,仍然没有变化

before, a=1,b=2
after, a=1,b=2

为什么呢?来看源码,Integer 的value是final类型的,一旦赋值,不能被修改
在这里插入图片描述
难道就没办法了吗?
答案是有的,那就是用反射

private static void swapWithRef(Integer i1, Integer i2) throws NoSuchFieldException, IllegalAccessException {
        Field field = Integer.class.getDeclaredField("value");
        field.setAccessible(true);//绕过安全检查
        Integer temp = i1;
        field.set(i1,i2);
        field.set(i2,temp);

    }

这里还有一个面试题,就是setAccessible 底层是怎么实现的?
在这里插入图片描述
这里讲一个成员变量设置为你设置的值(true);
然后在set操作的时候,会根据这个成员变量的值去验证或者不验证权限
在这里插入图片描述

但是结果依旧不对

before, a=1,b=2
after, a=2,b=2
Integer a =1 相当于  Integer a  = Integer.valueOf(1); // 自动装箱

在这里插入图片描述
在这里插入图片描述
从上面的源码可以得知,在[-128,127] 之间的范围,已经缓存起来了。
在这里插入图片描述
如果 a 和 b 在这个范围内[-128,127];
使用如下代码是相等的

a == b  // true;
// 但是如果  超出范围,是返回的false;
Integer c = 129;
Integer d = 129;
c == d   // false

我们继续来看刚才的问题

private static void swapWithRef(Integer i1, Integer i2) throws NoSuchFieldException, IllegalAccessException {
        Field field = Integer.class.getDeclaredField("value");
        field.setAccessible(true);//绕过安全检查
        Integer temp = new Integer(i1);// 问题出在这,这里使用一个新的地址,不受自动装箱和缓存的影响
        field.set(i1,i2);
        field.set(i2,temp);

    }
before, a=1,b=2
after, a=2,b=1

这次结果是正确的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值