4

せっかちな人のための Scala第 15 章 演習 10: メソッドに追加assert(n >= 0factorialます。factorial(-1)アサーションを有効にしてコンパイルし、例外がスローされることを確認します。アサーションなしでコンパイルします。何が起こるのですか?javapアサーション呼び出しに何が起こったかを確認するために使用します。

私のコード:

object Test {
  def factorial(x: Int): Int = {
    assert(x >= 0, "Call to factorial must be >= 0!")
    x match {
      case 0 => 1
      case x: Int => x * factorial(x - 1)
    }
  }

  def main(args: Array[String]): Unit = {
    factorial(-1)
  }
}

scalac最初に でコンパイルし、 を使用して検査しjavap Test、次に で再度コンパイルしscalac -Xelide-below MAXIMUMて同じコマンドで検査しました - 2 つの違いを見つけることができないようです。

プログラムを実行しようとすると、アサーションを使用してコンパイルすると例外がスローされ、アサーションを使用せずにコンパイルするとスタックオーバーフローエラーが発生することは理解していますが、違いがわかりませんjavap...

4

1 に答える 1

5

これを試してみるとjavap -v、アサーションが有効になっているバージョンでは次の行が見つかりますが、他の行では見つかりません。

   20:  invokevirtual   #27; //Method scala/Predef$.assert:(ZLscala/Function0;)V
   ...
   27:  if_icmpne       34
   30:  iconst_1
   31:  goto    55

それで、それは確かに大丈夫に見えます。

問題は、バイトコードを見ていないこと (-cまたは-vにフラグが必要javap) か、より可能性が高いのは、 ではなくjavapTestクラスの の出力を見ていることですTest$詳細については、Scala でのプログラミングの例を参照してください。

すべての Scala シングルトン オブジェクトに対して、コンパイラはオブジェクトの Java クラスを作成し、末尾にドル記号を追加します。という名前のシングルトン オブジェクトAppの場合、コンパイラは という名前の Java クラスを生成します App$。このクラスには、Scala シングルトン オブジェクトのすべてのメソッドとフィールドがあります。

Test.classコンパイルしたディレクトリの内容を一覧表示すると、との両方が表示されますTest$.class。を使用javap -v Test$すると、後者が表示されます。違いはここにあります。

于 2012-07-08T14:23:52.833 に答える