Подтвердить что ты не робот

Как выражения Lambda переводятся в байт-код Java

Я пытаюсь создать пример с использованием выражения lambda в java, и я использую официальный JDK8. Мой пример успешно выполнен. Но когда я пытаюсь проверить, как компилятор переводит лямбда-выражение в байтовый код, это вызывает у меня некоторую путаницу. Следующим является код моего примера: -

public class LambdaTest {
    public Integer lambdaBinaryOpertor(BinaryOperator<Integer> binaryOperator) {
        return binaryOperator.apply(60, 72);
    }

    public static void main(String[] args) {
        LambdaTest test = new LambdaTest();
        BinaryOperator<Integer> binaryOperator = (a, b) -> a*b;
        System.out.println("Additon using Lambda BinaryOperator: "+test.lambdaBinaryOpertor(binaryOperator));
    }
}

В этой статье они обсуждают, как компилятор переводит лямбда-выражения в байтовый код. В соответствии с этим документом выражение лямбда преобразуется в метод static и место, где объявляется лямбда-выражение, имеет ссылку на метод лямбда static. Следующий пример приведен в следующей статье:

//Source code
class A {
    public void foo() {
        List<String> list = ...
        list.forEach( s -> { System.out.println(s); } );
    }
} 

//After compile above code "translate code " 
class A {
    public void foo() {
        List<String> list = ...
        list.forEach( [lambda for lambda$1 as Block] );
    }

    static void lambda$1(String s) {
        System.out.println(s);
    }
}

Мой пример работает нормально и дает нам соответствующий результат. Но когда я пытаюсь запустить команду javap для проверки байтового кода класса, статический метод для lambdas в байтовом коде отсутствует.

c:\>javap LambdaTest
Compiled from "LambdaTest.java"
public class LambdaTest {
public LambdaTest();
public java.lang.Integer lambdaBinaryOpertor(java.util.function.BinaryOperator <java.lang.Integer>);
public static void main(java.lang.String[]);
}

В случае generics метод bridge создается компилятором, и мы также будем проверять этот метод с помощью команды javap, но в случае lambdas нет метода static. Статья была опубликована в 2012 году, а java 8 была запущена в марте 2014 года. Поэтому у меня есть некоторые вопросы относительно транснациональной лямбда:

  • Есть ли какая-либо новая реализация, используемая для lambda в JDK 8 после выпуска этой статьи, или я сделаю что-то неправильно, чтобы проверить метод лямбда?
  • Как действительно компилятор имеет дело с выражением лямбда?
  • Как JVM вызывает lambda exression?
4b9b3361

Ответ 1

Используйте javap дополнительные аргументы для печати полной информации о классе: javap -v -p -s -c

В вашем примере исходным кодом лямбда будет:

private static java.lang.Integer lambda$main$0(java.lang.Integer, java.lang.Integer);
    descriptor: (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0       
         1: invokevirtual #17                 // Method java/lang/Integer.intValue:()I
         4: aload_1       
         5: invokevirtual #17                 // Method java/lang/Integer.intValue:()I
         8: imul          
         9: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        12: areturn       
      LineNumberTable:
        line 10: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0     a   Ljava/lang/Integer;
            0      13     1     b   Ljava/lang/Integer;
}