问题
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