Integer缓存之如何让java算数运算1+1=3?
这次我们来玩点大的,当我们运行如下代码时,我们都会斩钉截铁的咆哮道这输出结果肯定是:2
没错,下面这段代码运行结果必须是2,三岁小孩都知道1+1=2。
public class Calc {
public static void main(String[] args) throws Exception{
//todo
Integer i = 1;
Integer j = 1;
Integer w = i + j;
System.out.println(w);
}
}
那么问题来了,如果我们在//todo那里注入几行代码,能否让我们的1+1=3呢?
没错,必须可以!
public class Calc {
public static void main(String[] args) throws Exception{
Class clz = Integer.class.getDeclaredClasses()[0];
Field cacheField = clz.getDeclaredField("cache");
cacheField.setAccessible(true);
Integer[] cache = (Integer[])cacheField.get(clz);
cache[130] = 3;
Integer i = 1;
Integer j = 1;
Integer w = i + j;
System.out.println(w);
}
}
当我们运行上面这段代码时,我们会神奇的发现,没错1+1=3!
解读:java中的Integer包装类中有一个私有的静态类IntegerCache,该静态类中有一个Integer类型的缓存数组,
java实例化Integer变量时,会先从这个缓存数组中取对应的值。上面的代码cache[130] = 3;
其中下标130就是
整数2的缓存位置,相当于我们把整数2这个缓存值改成了3。这时我们java的所有Integer类型的变量值为2的全部
变成了3。造成算术计算混乱。
然而这个缓存数组具体缓存了哪些值呢,我们循环打印一下即可发现天机,java默认缓存了-128至127这些整数。
public class Calc {
public static void main(String[] args) throws Exception{
Class clz = Integer.class.getDeclaredClasses()[0];
Field cacheField = clz.getDeclaredField("cache");
cacheField.setAccessible(true);
Integer[] cache = (Integer[])cacheField.get(clz);
cache[130] = 3;
for(int i=0; i<cache.length; i++){
System.out.println("下标为" + i + "的值为" + cache[i]);
}
}
}
结果输出:
下标为0的值为-128
下标为1的值为-127
下标为2的值为-126
下标为3的值为-125
下标为4的值为-124
下标为5的值为-123
下标为6的值为-122
下标为7的值为-121
下标为8的值为-120
下标为9的值为-119
.................
.................
.................
下标为245的值为117
下标为246的值为118
下标为247的值为119
下标为248的值为120
下标为249的值为121
下标为250的值为122
下标为251的值为123
下标为252的值为124
下标为253的值为125
下标为254的值为126
下标为255的值为127