Проблема с созданием другого байтового кода - PullRequest
0 голосов
/ 24 мая 2018

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

Например,

scala> def compare(flag: Boolean) = {
     | flag match{
     | case true => println("true..")
     | case false => println("false...")
     | }}
compare: (flag: Boolean)Unit

scala> :javap -c compare
Compiled from "<console>"
public class $line4.$read$$iw$$iw$ {
  public static $line4.$read$$iw$$iw$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class $line4/$read$$iw$$iw$
       3: invokespecial #17                 // Method "<init>":()V
       6: return

  public void compare(boolean);
    Code:
       0: iload_1
       1: istore_3
       2: iconst_1
       3: iload_3
       4: if_icmpne     22
       7: getstatic     #25                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
      10: ldc           #27                 // String true..
      12: invokevirtual #31                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      15: getstatic     #37                 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
      18: astore_2
      19: goto          60
      22: goto          25
      25: iconst_0
      26: iload_3
      27: if_icmpne     45
      30: getstatic     #25                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
      33: ldc           #39                 // String false...
      35: invokevirtual #31                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      38: getstatic     #37                 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
      41: astore_2
      42: goto          60
      45: goto          48
      48: new           #41                 // class scala/MatchError
      51: dup
      52: iload_3
      53: invokestatic  #47                 // Method scala/runtime/BoxesRunTime.boxToBoolean:(Z)Ljava/lang/Boolean;
      56: invokespecial #49                 // Method scala/MatchError."<init>":(Ljava/lang/Object;)V
      59: athrow
      60: return

  public $line4.$read$$iw$$iw$();
    Code:
       0: aload_0
       1: invokespecial #52                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #54                 // Field MODULE$:L$line4/$read$$iw$$iw$;
       8: return
}

Когда я делаю то же самое, используя выражение if, есть разныеБайт-код.

scala> def compareAgain(flag: Boolean) = {
     | if(flag) println("true..")
     | else println("false...")
     | }
compareAgain: (flag: Boolean)Unit

scala> :javap -c compareAgain
Compiled from "<console>"
public class $line5.$read$$iw$$iw$ {
  public static $line5.$read$$iw$$iw$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class $line5/$read$$iw$$iw$
       3: invokespecial #17                 // Method "<init>":()V
       6: return

  public void compareAgain(boolean);
    Code:
       0: iload_1
       1: ifeq          15
       4: getstatic     #25                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       7: ldc           #27                 // String true..
       9: invokevirtual #31                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      12: goto          23
      15: getstatic     #25                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
      18: ldc           #33                 // String false...
      20: invokevirtual #31                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      23: return

  public $line5.$read$$iw$$iw$();
    Code:
       0: aload_0
       1: invokespecial #36                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #38                 // Field MODULE$:L$line5/$read$$iw$$iw$;
       8: return
}

Существует другой байт-код.Что это значит в первом байт-коде?

// Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Это дубликат этого вопроса , на который был дан ответ для старого сопоставителя шаблонов и старого бэкэнда.Обратите внимание, как тогда жизнь была проще.

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

$ scala -opt:copy-propagation
Welcome to Scala 2.12.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_144).
Type in expressions for evaluation. Or try :help.

scala> def f(b: Boolean) = b match { case true => println() ; case _ => println() }
f: (b: Boolean)Unit

scala> :javap -c f
Compiled from "<console>"
public class $line3.$read$$iw$$iw$ {
  public static $line3.$read$$iw$$iw$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class $line3/$read$$iw$$iw$
       3: invokespecial #17                 // Method "<init>":()V
       6: return

  public void f(boolean);
    Code:
       0: iconst_1
       1: iload_1
       2: if_icmpne     14
       5: getstatic     #25                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       8: invokevirtual #28                 // Method scala/Predef$.println:()V
      11: goto          26
      14: goto          17
      17: getstatic     #25                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
      20: invokevirtual #28                 // Method scala/Predef$.println:()V
      23: goto          26
      26: return

  public $line3.$read$$iw$$iw$();
    Code:
       0: aload_0
       1: invokespecial #31                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: putstatic     #33                 // Field MODULE$:L$line3/$read$$iw$$iw$;
       8: return
}
0 голосов
/ 24 мая 2018

Выражения соответствия - это просто выраженияОни оценивают в ценность.В этом случае вы не используете значение, но компилятор включил код в любом случае.Поскольку println не возвращает ничего полезного, он оценивается как то, что называется тип блока , что примерно эквивалентно Void.

Случай выражения совпадения также отличается от случая if else в том, чтоесли аргумент не является ни истиной, ни ложью, генерируется новый MatchError.Конечно, этот случай недоступен, если вы не используете пользовательский байт-код для создания логического значения с неожиданным значением, но компилятор не пытался его оптимизировать.

...