为什么 scalac 需要在需要“Any"的方法中装箱“Int" [英] Why does scalac need to box an `Int` in a method expecting an `Any`
问题描述
考虑以下类:
package test
class Test {
def main(args: Array[String]): Unit = {
val i: Int = 0
println(i)
}
}
main
的字节码为:
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
可以看出,当我们调用 println
时,Int
被装箱成一个 java.lang.Integer
.但是println
的签名是:
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
作为 Int <: AnyVal <: Any
,为什么 Int
需要在调用中装箱?
As Int <: AnyVal <: Any
, why does the Int
need to get boxed in the call?
推荐答案
Any
可以在 Scala 中在语法上使用,因为编译器自动装箱任何 Java 原始类型(这就是 Int
code> 相当于) 根据需要.从发出的字节码中,您可以看到 INVOKEVIRTUAL
在具有以下签名的方法上被调用:
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
由于Java中没有Any
的概念,scalac发出Object
的方法签名,在Scala中相当于AnyRef
.由于Int
扩展了AnyVal
,我们需要分配等效的Java 包装器,即Integer
.
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
.
这篇关于为什么 scalac 需要在需要“Any"的方法中装箱“Int"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!