Разница в javap при компиляции с/без утверждения

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)
  }
}

Сначала я скомпилировал с помощью scalac, проверил с помощью javap Test, затем снова скомпилировал с помощью scalac -Xelide-below MAXIMUM и проверил с помощью той же команды - похоже, я не могу найти разницу между ними.

Я понимаю, что компиляция с утверждениями вызовет исключение при попытке выполнить программу, а компиляция без утверждений вызовет ошибку переполнения стека, но я не могу найти разницу в javap...


person adelbertc    schedule 08.07.2012    source источник


Ответы (1)


Когда я пробую это с 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), либо, что гораздо более вероятно, вы смотрите на вывод javap для класса Test, а не Test$. См., например, Программирование на Scala для более подробной информации:

Для каждого одноэлементного объекта Scala компилятор создаст класс Java для объекта со знаком доллара, добавленным в конце. Для одноэлементного объекта с именем App компилятор создает класс Java с именем App$. Этот класс имеет все методы и поля одноэлементного объекта Scala.

Если вы перечислите содержимое каталога, в который вы скомпилировали, вы увидите как Test.class, так и Test$.class. Использование javap -v Test$ покажет вам последнее, и именно здесь вы найдете разницу.

person Travis Brown    schedule 08.07.2012