Java包装类Integer的相关问题&Integer类型对象互换value的swap方法(反射修改缓冲区)

目录

1.首先是Integer类型赋给int型的自动拆箱操作

2.int类型赋给Integer类型的自动装箱操作

3.Integer类型对象互换value的swap方法

最后该问题的代码实现可以为:


1.首先是Integer类型赋给int型的自动拆箱操作

Integer a = 1;

int i = a.intValue();//拆箱操作
int j = a;//自动拆箱操作,等价于int j = a.intValue();

inValue方法直接返回value值,没什么好说的

2.int类型赋给Integer类型的自动装箱操作

int i = 2;

Integer a = Integer.valueOf(i);//装箱操作

Integer b = i;//自动装箱操作,等价于Integer b = Integer.valueOf(i);

首先我们来看装箱操作的源码:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

可以看到Java为装箱操作提供了缓冲区,数值范围是-128~127,因此我们会得到以下测试结果

System.out.println(new Integer(127) == new Integer(127)); //false, object类型的比较
System.out.println(Integer.parseInt("128")==Integer.parseInt("128")); //true, int 类型的比较
System.out.println(Integer.valueOf("127")==Integer.valueOf("127")); //true ,object 类型的比较,但是IntegerCache return a same object
System.out.println(Integer.valueOf("128")==Integer.valueOf("128")); //false ,object 类型的比较,但是数值超过了缓冲区范围
System.out.println(128==Integer.valueOf(128)); //true , int类型的比较
System.out.println(1==Integer.valueOf(1));//true,int类型的比较

3.Integer类型对象互换value的swap方法

有这样一道题目:

public class IntegerTest {
    public static void main(String[] args) {
        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) {

        //请实现
    }

}

Integer在方法中没有提供value的get和set方法,也是对对象的安全保护,也就是传递过程中在Integer里面copy了一个副本指向值,而不是引用地址,直接写

int temp = numa;

numa = numb;

numb = temp
是无法实现的,我们可以用反射改变Integer内部的value属性值。

注意:反射绕过安全保护直接修改内部数据,使用反射强行修改的时候请慎重

利用反射实现代码:

public static void swap(Integer numa,Integer numb) {
        try {
            Field field = Integer.class.getDeclaredField("value");
            field.setAccessible(true);
            int temp = numa;
            field.set(numa,numb);
            field.set(numb,temp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

但实际运行结果却是:

a=1,b=2
a=2,b=2

问题就出在

field.set(numa,numb);

这个操作把缓冲区修改了

由于numa和numb都在缓冲区,自动装箱操作使得

a = IntegerCache.cache[1 + -(-128)]  //cache[129]
b = IntegerCache.cache[2 + -(-128)]     //cache[130]

现在field使用反射强行修改值,这样的操作一直都是不安全的操作,这里就是一个非常典型的例子!

//field.set(numa,numb)修改了cache[129]的值,其实就是

cache[129] = b.intValue()  // 现在cache[129] 值被修改为 2

接下来

field.set(numb,temp);

这里会装箱, 也就是 temp装箱执行代码

IntegerCache.cache[temp + -(-128)]  // temp = 1

//现在执行field.set(numb,temp)其实就是

cache[130] = cache[129]; //cache[129] 值为2

使用反射修改缓冲区,会使得缓冲区完全错乱,所以大家要牢记不要滥用反射去修改那些java保护起来的东西,java做好的保护不让你碰其实就是怕你掉进坑了,所以使用反射的时候千万要思考周全以后再来使用

最后该问题的代码实现可以为:

  public static void swap(Integer numa,Integer numb) {

        try {
            Field field = Integer.class.getDeclaredField("value");
            field.setAccessible(true);
            int temp = numa;
            field.setInt(numa,numb);
            field.setInt(numb,temp);

        } catch (Exception e) {
            e.printStackTrace();
        }

  }

这段代码也修改了缓冲区

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值