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