分享一道java面试题 Integer值交换

1.题目

        Integer a = 1;
        Integer b = 2;
        System.out.println("before----a=" + a + ",b=" + b);
        swap(a, b);
        System.out.println("after----a=" + a + ",b=" + b);

交换a和b的值
输出结果为a=2,b=1

2.思路

定义临时变量tmp,tmp=a;a=b;b=tmp

2.1代码v1.0

public class IntegerTest {
    public static void main(String[] args) {
        Integer a = 1;
        Integer 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 a, Integer b) {
        Integer tmp;
        tmp = a;
        a = b;
        b = tmp;
    }
}

输出结果:
在这里插入图片描述
并未交换成功?
原因在上一篇博客做了说明:
java是值传递还是引用传递?

从这个结果可以看出,swap方法传递的是值,因为交换a,b的值之后,原来的对象没有发生变化;
如果是引用传递,交换的是对象引用的地址,a,b就会发生变化,实际上却没有;
其实swap中传递的a,b只是传递的a,b值的副本,对副本进行操作不会影响原来的值。

2.2代码v2.0

了解了其中的原因,解题思路,和user.setName()类似,Integer也是对象,当然也可以setInt(),使用反射
代码:

public class IntegerTest5 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Integer a = 1;
        Integer b = 2;
        System.out.println("before----a=" + a + ",b=" + b);
        swap2(a, b);
        System.out.println("after----a=" + a + ",b=" + b);
    }

    private static void swap(Integer a, Integer b) throws NoSuchFieldException, IllegalAccessException {
        Field field = Integer.class.getDeclaredField("value");
        field.setAccessible(true);
        int aInt = field.getInt(a);
        Integer tmp;
        tmp = aInt;
        field.setInt(a,field.getInt(b));
        field.setInt(b,tmp);
    }
}

为啥要用field.setAccessible(true);?
因为Integer的实现方式 private final int value;
final类型不能被修改,·setAccessible(true);之后可以跳过jdk的检查。

原理是Field继承了AccessibleObjectsetInt()时会检查override的值
setAccessible(true)可以修改override的值,使其绕过这一段检查

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
执行结果:
在这里插入图片描述
a的值确实变成了2,但是b的值还是为2,并未变成1,继续往下看。

2.3代码v3.0

继续踩坑ing…?
为啥b的值没有改变,这里原因和Integer的自动装箱有关系,Integer a =1 , 1是int基本类型,但是这里用Integer接收,jdk会自动装箱。
Integer a =1Integer a = Integer.valueOf(1);
Integer 源码:
在这里插入图片描述
关键点就在IntegerCache,当对象的值在-128~127之间的时候,对象的值实际上是存储在缓存中的,

why?为啥Integer要这么设计?

因为我们在使用Integer大部分情况下都是在-128~127之间,这么设计可以提高效率减少内存分配
在这里插入图片描述
这样产生的问题

        Integer tmp;
        tmp = aInt;
        field.setInt(a,field.getInt(b));
        field.setInt(b,tmp);

在最后一步设置b的值为tmp的时候,tmp的值实际上是a的缓存cache[k]中的值,但是这个值在field.setInt(a,field.getInt(b));的时候已经被替换为2,所以最后b设置的值为更新之后缓存cache[k]中的2。

2.3.1解决思路一

    private static void swap1(Integer a, Integer b) throws NoSuchFieldException, IllegalAccessException {
       Field field = Integer.class.getDeclaredField("value");
       field.setAccessible(true);
       int aInt = field.getInt(a)+128;
       Integer tmp;
       tmp = aInt;
       field.setInt(a,field.getInt(b));
       field.setInt(b,tmp-128);
   }

2.3.2解决思路二

    private static void swap2(Integer a, Integer b) throws NoSuchFieldException, IllegalAccessException {
       Field field = Integer.class.getDeclaredField("value");
       field.setAccessible(true);
       int aInt = field.getInt(a);
       Integer tmp = new Integer(aInt);
       field.setInt(a,field.getInt(b));
       field.setInt(b,tmp);
   }

测试结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值