为什么 scalac 需要在需要“Any"的方法中装箱“Int" [英] Why does scalac need to box an `Int` in a method expecting an `Any`

查看:39
本文介绍了为什么 scalac 需要在需要“Any"的方法中装箱“Int"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下类:

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 原始类型(这就是 Intcode> 相当于) 根据需要.从发出的字节码中,您可以看到 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆