原出处是国外某论坛某帖子中楼主提问:如何让1+1=3?
于是出现了各种语言实现的各种机制的答案,当然其中也包括直接用字符串输出"1+1=3"...
最后被采纳的是用Java语言实现的答案。
以下是答案:
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException { Class cache = Integer.class.getDeclaredClasses()[0]; Field c = cache.getDeclaredField("cache"); c.setAccessible(true); Integer[] array = (Integer[]) c.get(cache); array[130] = array[131]; System.out.printf("%d", 1 + 1); }
作者解释:
You need to change it even deeper than you can typically access. Note that this is designed for Java 6 with no funky parameters passed in on the JVM that would otherwise change the IntegerCache.
Deep within the Integer class is a Flyweight of Integers. This is an array of Integers from 128 to +127. cache[132] is the spot where 4 would normally be. Set it to 5.
这样思路已经很明确了。
Integer.class.getDeclaredClasses()[0]指向IntegerCache类,其cache域在静态初始化块内进行初始化,缓存-128到127,由此可知cache[130]==2。
static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low)); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); }
看到这里便恍然大悟,几乎使用Java有一段时间的人都知道这一点,于是写出了如下代码,只可惜运行结果仍然是2:
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException { Class cache = Integer.class.getDeclaredClasses()[0]; Field c = cache.getDeclaredField("cache"); c.setAccessible(true); Integer[] array = (Integer[]) c.get(cache); array[130] = array[131]; System.out.println(1+1); }
问题就出在printf还是println。
参考println的方法声明,作者对于不同的基本类型都提供了overwrite,而printf并没有为基本类型提供方法。
虽说printf("%d",1+1)相当于System.out.println(String.format("%d", 1 + 1));
但问题的本质还是在于println(1+1)的结果仍是基本类型,并没有进行装箱。
即,System.out.println((Integer)1+1);的结果为3.
Java - 机智地让1+1的结果变成3