Why does scalac need to box an `Int` in a method expecting an `Any`

让人想犯罪 __ 提交于 2019-12-23 12:44:01

问题


Consider the following class:

package test
class Test {
  def main(args: Array[String]): Unit = {
    val i: Int = 0
    println(i)
  }
}

The bytecode of main is:

public main([Ljava/lang/String;)V
   // parameter final  args
  L0
   LINENUMBER 4 L0
   ICONST_0
  L1
   ISTORE 2
  L2
   LINENUMBER 5 L2
   GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$;
   ILOAD 2
   INVOKESTATIC scala/runtime/BoxesRunTime.boxToInteger (I)Ljava/lang/Integer;
   INVOKEVIRTUAL scala/Predef$.println (Ljava/lang/Object;)V
  L3
   RETURN
  L4
   LOCALVARIABLE i I L1 L3 2
   LOCALVARIABLE this Ltest/Test; L0 L4 0
   LOCALVARIABLE args [Ljava/lang/String; L0 L4 1
   MAXSTACK = 2
   MAXLOCALS = 3

As can be seen, when we call println, the Int gets boxed into a java.lang.Integer. But the signature of println is:

def println(x: Any): Unit

As Int <: AnyVal <: Any, why does the Int need to get boxed in the call?


回答1:


Any can be syntactically used in Scala since the compiler auto boxes any Java primitive type (which is what Int is equivalent to) as needed. From the emitted byte code, you see that INVOKEVIRTUAL is called on a method with the following signature:

scala/Predef$.println (Ljava/lang/Object;)V

Since there is no notion of Any in Java, scalac emits method signature of Object, which in Scala is equivalent to AnyRef. Since Int extends AnyVal, we need to allocate the equivalent Java wrapper, which is Integer.



来源:https://stackoverflow.com/questions/47156541/why-does-scalac-need-to-box-an-int-in-a-method-expecting-an-any

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!