使用/不使用断言进行编译时的javap差异

时间:2012-07-08 06:20:23

标签: scala javap

Scala for the Impatient 第15章练习10:将assert(n >= 0添加到factorial方法。在启用断言的情况下进行编译,并验证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再次编译并使用相同的命令进行检查 - 我似乎无法找到两者之间的区别

我理解使用断言进行编译会在我尝试执行程序时抛出异常,而没有断言的编译会导致堆栈溢出错误,但我找不到javap中的差异......

1 个答案:

答案 0 :(得分: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$。有关更多详细信息,请参阅 Programming in Scala

  

对于每个Scala单例对象,编译器都将创建一个Java   具有美元符号的对象的类添加到结尾。为一个   单件对象名为App,编译器生成一个名为的Java类   App$。该类包含Scala的所有方法和字段   单身对象。

如果列出您编译的目录的内容,您将看到Test.classTest$.class。使用javap -v Test$会向您显示后者,您可以在这里找到差异。