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并使用相同的命令检查 - 我似乎无法找到两者之间的区别。

我知道当我尝试执行程序时使用断言编译会抛出异常,而没有断言编译会导致堆栈溢出错误,但我找不到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

所以这看起来肯定没问题。

问题可能是您没有查看字节码(这需要-cor-v标志javap),或者 - 更有可能 - 您正在查看类的输出javapTest而不是Test$. 有关更多详细信息,请参见示例Scala 中的编程:

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

如果您列出已编译的目录的内容,您将看到Test.classTest$.class。Usingjavap -v Test$会告诉你后者,这就是你会发现不同之处的地方。

于 2012-07-08T14:23:52.833 回答