【问题标题】:How to modify integer addition in java?如何在java中修改整数加法?
【发布时间】:2023-03-26 21:34:01
【问题描述】:

所以基本上我在做一些研究,因为我很想知道它是否可以完成,我发现了这段代码:

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。

【问题讨论】:

  • println(n) 根本不使用 java.lang.Integer 类。 printf 确实如此,因为每个参数都被装箱了,因为所有参数都必须是对象。

标签: java class caching integer field


【解决方案1】:

Java 缓存 256 个 Integer 对象,表示从 -128 到 127 的数字。当 int 被装箱到 Integer 时,如果它的值介于 -128 和 127 之间,缓存中的 Integer 对象将会被使用。 (Learn more here)。语言如何做到这一点是实现细节。在您的 Java 版本中,它将缓存存储在 Integer 的内部类中,在名为 cacheInteger[] 字段中。在其他 Java 版本中,这可能会发生变化,因此您的代码可能会中断。

代码的第一部分是获取整数缓存,并将索引 132 设置为与索引 133 相同。由于此数组从 -128 开始,索引 132 将对应于 4 所在的位置,并且索引133 将是 5 的位置。这意味着您已将缓存中的 4 替换为 5。

printf2 + 2 的参数首先被评估为 4。然后它被装箱为 Integer。这是因为printf 只接受Object 作为其第二个参数。因为 4 在 -128 和 127 之间,所以使用了缓存,并且访问了数组的索引 132,因为如果您没有修改数组,那将是 Integer 4 所在的位置。但是你已经修改了数组,所以它变成了 5。

另一方面,println 仍然打印 4,因为 println 有一个接受 int 的重载,所以那里不会发生装箱。

顺便说一句,你不是在修改“整数加法”,你只是在修改“整数装箱”。

【讨论】:

  • re 你只是在修改“整数装箱”——或者我们通常说的“破坏内存”:-)
  • 谢谢,这是一个有用的解释。我也想知道,是否可以在我的 println 中制作 2+2=5 而无需将其装箱为整数,还是不可能?
  • 正如我所说,你永远不会制作2 + 2 = 5。你只是在制作4 = 5。如果我printf 1+3,我仍然会得到 5。无论如何,你可以用 int 做的很少。也许是自修改代码?不过说真的,这两种方法都非常不安全和不可靠。他们可以很容易地闯入另一个 Java 版本。 @ShreyVarma
  • 好吧,我明白你的意思了。是的,我从没想过使用这段代码,我只是想看看它是如何工作的。
猜你喜欢
  • 2012-08-23
  • 1970-01-01
  • 2015-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-20
  • 1970-01-01
  • 2023-03-19
相关资源
最近更新 更多