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

Что такое выражение Java 8 Lambda, скомпилированное?

Рассмотрим следующий фрагмент Java 8.

public static void main(String[] args) {            
   List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);

   Consumer<Integer>  consumer = x -> System.out.print(x);  

   integers.forEach(consumer);
}

Что скомпилировано Consumer<Integer> consumer = x -> System.out.print(x)?

Я понимаю, что Lambdas не реализованы как анонимные внутренние классы. Однако Consumer<Integer> является интерфейсом, поэтому x -> System.out.print(x) должен создавать какой-то объект, но неясно, какой объект создается.

Есть ли какой-нибудь новый тип объекта в Java 8 для представления лямбда-выражения?

Обновить. Вот декомпилированная программа, которую программа выполнила с помощью jQuery eclipse java 8, а выход ниже - из eclipse, когда вы открываете файл класса.

Похоже, что выражение лямбда превращается в статический метод класса, который содержит лямбда-выражение private static synthetic void lambda$0(java.lang.Integer x);

// Compiled from Example.java (version 1.8 : 52.0, super bit)
public class Example {

  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public Example();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 7]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: Example

  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 4, Locals: 3
  public static void main(java.lang.String[] args);
     0  iconst_5
     1  anewarray java.lang.Integer [16]
     4  dup
     5  iconst_0
     6  iconst_1
     7  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    10  aastore
    11  dup
    12  iconst_1
    13  iconst_2
    14  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    17  aastore
    18  dup
    19  iconst_2
    20  iconst_3
    21  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    24  aastore
    25  dup
    26  iconst_3
    27  iconst_4
    28  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    31  aastore
    32  dup
    33  iconst_4
    34  iconst_5
    35  invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [18]
    38  aastore
    39  invokestatic java.util.Arrays.asList(java.lang.Object[]) : java.util.List [22]
    42  astore_1 [integers]
    43  invokedynamic 0 accept() : java.util.function.Consumer [31]
    48  astore_2 [consumer]
    49  getstatic java.lang.System.out : java.io.PrintStream [32]
    52  aload_2 [consumer]
    53  invokevirtual java.lang.Object.getClass() : java.lang.Class [38]
    56  invokevirtual java.lang.Class.getCanonicalName() : java.lang.String [42]
    59  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
    62  getstatic java.lang.System.out : java.io.PrintStream [32]
    65  aload_2 [consumer]
    66  invokevirtual java.lang.Object.getClass() : java.lang.Class [38]
    69  invokevirtual java.lang.Class.getTypeName() : java.lang.String [54]
    72  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
    75  aload_1 [integers]
    76  aload_2 [consumer]
    77  invokeinterface java.util.List.forEach(java.util.function.Consumer) : void [57] [nargs: 2]
    82  return
      Line numbers:
        [pc: 0, line: 10]
        [pc: 43, line: 12]
        [pc: 49, line: 14]
        [pc: 62, line: 15]
        [pc: 75, line: 17]
        [pc: 82, line: 18]
      Local variable table:
        [pc: 0, pc: 83] local: args index: 0 type: java.lang.String[]
        [pc: 43, pc: 83] local: integers index: 1 type: java.util.List
        [pc: 49, pc: 83] local: consumer index: 2 type: java.util.function.Consumer
      Local variable type table:
        [pc: 43, pc: 83] local: integers index: 1 type: java.util.List<java.lang.Integer>
        [pc: 49, pc: 83] local: consumer index: 2 type: java.util.function.Consumer<java.lang.Integer>

  // Method descriptor #73 (Ljava/lang/Integer;)V
  // Stack: 2, Locals: 1
  private static synthetic void lambda$0(java.lang.Integer x);
    0  getstatic java.lang.System.out : java.io.PrintStream [32]
    3  aload_0 [x]
    4  invokevirtual java.io.PrintStream.print(java.lang.Object) : void [74]
    7  return
      Line numbers:
        [pc: 0, line: 12]
      Local variable table:
        [pc: 0, pc: 8] local: x index: 0 type: java.lang.Integer

  Inner classes:
    [inner class info: #96 java/lang/invoke/MethodHandles$Lookup, outer class info: #98 java/lang/invoke/MethodHandles
     inner name: #100 Lookup, accessflags: 25 public static final]
Bootstrap methods:
  0 : # 89 arguments: {#90,#93,#94}
}
4b9b3361

Ответ 1

текущий черновик спецификации Java 8 Language Specification (глава 15.27.4)

Значение лямбда-выражения является ссылкой на экземпляр класс со следующими свойствами:

  • Класс реализует целевой функциональный интерфейс и, если целевой тип является типом пересечения, каждый другой элемент интерфейса пересечения.
  • Класс объявляет метод, который переопределяет абстрактные методы супертипа функционального интерфейса (и, возможно, некоторые другие методы его суперинтерфейсов).
  • Типы параметров метода, тип возвращаемого значения и типы сброса задаются типом функции интерфейса.
  • Тело метода влияет на оценку лямбда-тела, если оно является выражением или исполнением лямбда-тела, если оно является блок; если результат ожидается, он возвращается из метода.
  • Класс не отменяет других методов интерфейса или интерфейсов, упомянутых выше, за исключением того, что он может переопределять методы Objectкласс.

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

Таким образом, объект, возвращаемый лямбда-выражением

x -> System.out.print(x);  

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

С учетом вашего комментария, что

consumer.getClass()

возвращает следующий класс

Example$$Lambda$1/1072591677

кажется, что он генерирует прокси-подобный класс, специфичный для лямбда-выражений.

Смотрите здесь: