不耐烦的Scala第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)
}
}
Run Code Online (Sandbox Code Playgroud)
我scalac首先编译,使用检查它javap Test,然后再次编译scalac -Xelide-below MAXIMUM并使用相同的命令进行检查 - 我似乎无法找到两者之间的区别.
我理解使用断言进行编译会在我尝试执行程序时抛出异常,而没有断言的编译会导致堆栈溢出错误,但我找不到javap...
当我尝试这个时,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),或者,更可能,你正在寻找的输出javap为Test类,而不是Test$.有关更多详细信息,请参阅Scala中的编程:
对于每个Scala单例对象,编译器将为对象创建一个Java类,并在末尾添加一个美元符号.对于名为singleton的对象
App,编译器会生成一个名为的Java类App$.此类包含Scala单例对象的所有方法和字段.
如果列出您编译的目录的内容,您将看到Test.class和Test$.class.使用javap -v Test$会告诉你后者,这是你会发现差异的地方.