2017-11-07 2 views
4

を期待する方法で` Int`をボックスする必要がない次のクラスを考えてみましょう:はなぜscalacは `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と呼び出すと、Intjava.lang.Integerに囲まれます。しかしprintlnのシグネチャは次のとおりです。Int <: AnyVal <: Anyとして

def println(x: Any): Unit 

、なぜIntは、通話中に箱入りを取得する必要がありますか?

答えて

2

Anyは、コンパイラが任意のJavaプリミティブタイプ(これはIntと同等)を必要に応じて自動ボックス化するため、Scalaで構文的に使用できます。 JavaでAnyの概念がないので

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

、scalacはScalaで同等ですObjectのメソッドシグネチャを、放出:放出されたバイトコードから、INVOKEVIRTUALは、次のシグネチャを持つメソッドで呼び出されていることがわかりAnyRefIntAnyValに拡張されているので、対応するJavaラッパー(Integer)を割り当てる必要があります。

+0

Javaのようにprintlnがオーバーロードされていませんでしたか?_ –

+1

@oxbow_lakes Javaは 'println'のプリミティブな入力タイプを持っています。 'PrimitiveType.toString'、つまり' Integer.toString'は 'Integer'の割り当てを避けます。私は、もしあなたが 'println'をプロダクションにしたいならば、Integerか他のラッパーを割り当てることがあなたの問題の中で最も少なくなるだろうと実装者が仮定していたと仮定しています。 –

+1

私のような馬鹿を除けば、このことについてはあまり考えずに、そのスタイルをコピーして、パフォーマンスの意味に気付かないかもしれません –

関連する問題