英文:
How to modify integer addition in java?
问题
基本上我在做一些研究,因为我很好奇是否可以做到,然后我找到了这段代码:
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws Exception {
Class cache = Integer.class.getDeclaredClasses()[0];
Field c = cache.getDeclaredField("cache");
c.setAccessible(true);
Integer[] array = (Integer[]) c.get(cache);
array[132] = array[133];
int n = 2 + 2;
System.out.println(n);
System.out.printf("%d", 2 + 2);
}
}
我只是好奇为什么printf语句现在会返回5,但打印整数n仍然会给我4。
英文:
So basically I was doing some research because I was curious to see if it could be done and I found this code:
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws Exception {
Class cache = Integer.class.getDeclaredClasses()[0];
Field c = cache.getDeclaredField("cache");
c.setAccessible(true);
Integer[] array = (Integer[]) c.get(cache);
array[132] = array[133];
int n = 2+2;
System.out.println(n);
System.out.printf("%d",2 + 2);
}
}
I was simply curious why the printf statement would now return 5, but printing integer n would sill give me 4.
答案1
得分: 3
Java缓存了表示从-128到127的256个Integer
对象,当一个int
被装箱为一个Integer
时,如果其值在-128到127之间,将使用缓存中的Integer
对象。这是语言的实现细节。在您的Java版本中,它将此缓存存储在Integer
的一个内部类中,名为cache
的Integer[]
字段中。在其他某个版本的Java中,这可能会改变,因此您的代码可能会出错。
您的代码的第一部分所做的是获取整数缓存,并将索引132设置为与索引133相同。由于这个数组从-128开始,索引132对应于数字4的位置,索引133对应于数字5的位置。这意味着您已经用5替换了缓存中的4。
传递给printf
的参数2 + 2
首先被求值为4。然后它被装箱为一个Integer
。这是因为printf
只接受一个Object
作为其第二个参数。因为4在-128到127之间,所以使用了缓存,并且访问了数组的索引132,因为如果您没有修改数组,Integer
4本应在那里。但是您已经修改了数组,所以它变成了5。
另一方面,println
仍然打印4,因为println
有一个接受int
的重载,因此在那里不会进行装箱。
顺便说一下,您并没有修改"整数加法",您只是修改了"整数装箱"。
英文:
Java caches 256 Integer
objects representing the numbers from -128 to 127. When an int
gets boxed to an Integer
, if its value is between -128 and 127, the Integer
object from the cache will be used. (Learn more here). How the language does this is implementation detail. In your version of Java, it stores this cache in an inner class in Integer
, in an Integer[]
field called cache
. In some other version of Java, this might change, so your code might break.
What the first part of your code is doing, is getting the integer cache, and setting index 132 to be the same as index 133. Since this array starts from -128, index 132 would correspond to where 4 is, and index 133 would be where 5 is. This means you have replaced 4 in the cache with a 5.
The argument to printf
, 2 + 2
, first gets evaluated to 4. Then it gets boxed to an Integer
. This is because printf
only accepts an Object
as its second parameter. Because 4 is between -128 and 127, the cache is used, and index 132 of the array is accessed, because that's where the Integer
4 would have been, if you haven't modified the array. But you have modified the array, so it got 5 instead.
On the other hand, println
still prints 4 because println
has an overload that accepts int
, so no boxing occurs there.
By the way, you are not modifying "integer addition", you are just modifying "integer boxing".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论