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



Scala for the Impatient Chapter 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的差异......

当我尝试这样做时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(,要么更有可能的是,您正在查看Test类的javap输出,而不是Test$。例如,请参阅 Scala 中的编程以获取更多详细信息:

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

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

相关内容

  • 没有找到相关文章

最新更新