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

ade*_*rtc 4 scala javap

不耐烦的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)
  }
}
Run Code Online (Sandbox Code Playgroud)

scalac首先编译,使用检查它javap Test,然后再次编译scalac -Xelide-below MAXIMUM并使用相同的命令进行检查 - 我似乎无法找到两者之间的区别.

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

Tra*_*own 5

当我尝试这个时,javap -v我在启用了断言的版本中找到以下行,但在另一个中没有:

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

所以这当然看起来没问题.

该问题可能是,你要么不看字节码(这需要-c-v标志javap),或者,更可能,你正在寻找的输出javapTest类,而不是Test$.有关更多详细信息,请参阅Scala中的编程:

对于每个Scala单例对象,编译器将为对象创建一个Java类,并在末尾添加一个美元符号.对于名为singleton的对象App,编译器会生成一个名为的Java类 App$.此类包含Scala单例对象的所有方法和字段.

如果列出您编译的目录的内容,您将看到Test.classTest$.class.使用javap -v Test$会告诉你后者,这是你会发现差异的地方.