目录
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();
}
}
这段代码也修改了缓冲区