使用反射来重写 2 + 2 = 5。

huangapple go评论72阅读模式
英文:

Using reflection to override 2 + 2 = 5

问题

请容我稍等,我知道这是一个奇怪的问题。

我刚刚偶然发现了Java的反射库,特别是来自Lex Fridman的视频中覆盖了 2 + 2 = 5 的代码部分:

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];

        System.out.printf("%d", 2 + 2);
    }
}

我正在努力理解它的作用,并将其翻译成等效的Scala形式,但是它无法编译,因为 Int.getClass.getDeclaredClasses 返回一个空数组:

import java.lang.reflect.Field

val cache: Class[_] = Int.getClass.getDeclaredClasses.head
// 上面这行会抛出 java.util.NoSuchElementException: next on empty iterator

val c: Field = cache.getDeclaredField("cache")
c.setAccessible(true)
val array = c.get(cache).asInstanceOf[Array[Int]]
array(132) = 5

println(2 + 2)

当我尝试使用 classgetClass 时,它们都不是 Integer 下的方法,所以我尝试了 Int;我曾以为Scala的 Int 只是Java的 Integer 的包装器 - 这不是这种情况吗?

我还尝试过:

  • new Integer()(抱怨“构造函数Integer具有多个重载方法的选择”)
  • new Int()(“类Int是抽象的,无法实例化”)
  • 将Int和Integer都扩展为 class T extends Int ... new T.getClass....(从最终类进行非法继承)

为什么在Java中可以工作,但在Scala中无法编译?如何在Scala中实现我愚蠢的目标 2 + 2 = 5

英文:

Bear with me, I understand this is a weird problem to have.

I have just stumbled across Java's reflection library, specifically this bit of code from a video by Lex Fridman which overrides 2 + 2 = 5:

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];

        System.out.printf("%d",2 + 2);
    }
}

I am trying to wrap my head around what it's doing by translating it into its equivalent Scala form, but it isn't compiling as Int.getClass.getDeclaredClasses returns an empty array:

import java.lang.reflect.Field

val cache: Class[_] = Int.getClass.getDeclaredClasses.head
// above line throws java.util.NoSuchElementException: next on empty iterator

val c: Field = cache.getDeclaredField("cache")
c.setAccessible(true)
val array = c.get(cache).asInstanceOf[Array[Int]]
array(132) = 5

println(2+2)

Neitherclass nor getClass were methods under Integer when I tried using that, so I tried with Int instead; I was under the impression that Scala's Int is just a wrapper around Java's Integer - is this not the case?

I have also tried:

  • new Integer() (complained about "overloaded method constructor Integer with alternatives")
  • new Int() ("class Int is abstract; cannot be instantiated")
  • Extending both Int and Integer with class T extends Int ... new T.getClass.... (illegal inheritance from final class)

Why does this work in Java where it doesn't compile with Scala? How can I achieve my stupid goal of 2 + 2 = 5 in Scala?

答案1

得分: 5

java.lang.Integer 应该替代 scala.Int

Int.getClass 是在类 Int 的伴生对象上调用的 getClass,这是错误的。

代码翻译成 Scala 如下:

val cache = classOf[Integer].getDeclaredClasses.apply(0)
val c = cache.getDeclaredField("cache")
c.setAccessible(true)
val array = c.get(cache).asInstanceOf[Array[Integer]]
array(132) = array(133)
println(2 + 2) // 5

我原以为 Scala 的 Int 只是围绕 Java 的 Integer 的包装 - 这不是这种情况吗?

不是这样。通常情况下,scala.Int 对应于 Java 的 int

https://github.com/scala/scala/blob/2.13.x/src/library/scala/Int.scala

英文:

java.lang.Integer should be instead of scala.Int.

Int.getClass is getClass invoked on the companion object of class Int, which is wrong.

Translation of the code into Scala is

val cache = classOf[Integer].getDeclaredClasses.apply(0)
val c = cache.getDeclaredField("cache")
c.setAccessible(true)
val array = c.get(cache).asInstanceOf[Array[Integer]]
array(132) = array(133)
println(2 + 2) // 5

> I was under the impression that Scala's Int is just a wrapper around Java's Integer - is this not the case?

It's not. Normally scala.Int corresponds to Java int.

https://github.com/scala/scala/blob/2.13.x/src/library/scala/Int.scala

答案2

得分: 1

如果您查看Integer类中的IntegerCache内部类。部分实现如下:

        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

默认情况下,IntegerCache会缓存介于-128(low)和127(high)之间的整数(可能是因为在典型应用程序中这些整数使用最频繁)。缓存大小为256(以便将正负值放在一起)。

在您的应用程序中,您可以获取Integer类的“cache”字段,其中包含从-128到127的值。但在数组中,它们是连在一起的,因此值0的索引实际上是128(因为首先有-128个值)+ 0。

0 -> 128
1 -> 129
2 -> 130
3 -> 131
4 -> 132
5 -> 133

array[132] = array[133]表达式将在缓存中使4等于5。因此,每当应用程序从缓存中调用索引4时,将返回整数5。

至于Scala部分,我对Scala没有经验,但它不是使用JVM将自身编译为字节码吗?因此,Scala可能不使用JDK,其Int实现可能不同,这就是您遇到错误的原因(根据@Dmytro Mitin的回答,似乎有可能使用JDK中的Integer)。

英文:

If you check IntegerCache inner class inside Integer class. Some part of the implementation as follows:

        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k &lt; cache.length; k++)
            cache[k] = new Integer(j++);

By default Integers between -128 (low) and 127 (high) (probably choiced because these are the most used ones in a typical application). And cache size is 256 (so that - and + values will be keep together)

In your application, you get "cache" field of Integer class which is the values from -128 to 127. But in the array they keep together, so value 0 index is actually 128 (because there are -128 values first) + 0.

0 -&gt; 128
1 -&gt; 129
2 -&gt; 130
3 -&gt; 131
4 -&gt; 132
5 -&gt; 133

And your array[132] = array[133]; expression makes 4 = 5 in the cache. So whenever an application calls the index of 4 from the cache, Integer 5 will be returned.

For the Scala part, I don't have experience in Scala but does not it use the JVM just to compile itself to byte code? So maybe Scala does not use the JDK and its Int implementation is different which is the reason you get the error (seems like it is possible to use Integer from JDK based on @Dmytro Mitin's answer)

huangapple
  • 本文由 发表于 2020年9月5日 05:32:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63748255.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定