什么是Java 8 Lambda表达式编译?

请考虑以下Java 8代码段。

public static void main(String[] args) { List integers = Arrays.asList(1, 2, 3, 4, 5); Consumer consumer = x -> System.out.print(x); integers.forEach(consumer); } 

什么是Consumer consumer = x -> System.out.print(x)被编译到?

我知道Lambdas不是作为匿名内部类实现的。 但是Consumer是一个接口,因此x -> System.out.print(x)必须生成某种对象,但不清楚生成什么类型​​的对象。

Java 8中是否有一些新类型的对象代表lambda表达式?

更新这里是程序与eclipse java 8编译器一起编译的反编译程序,下面的输出是在打开类文件时来自eclipse。

看起来lambda表达式变成了包含lambda表达式的类的静态方法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 [pc: 49, pc: 83] local: consumer index: 2 type: java.util.function.Consumer // 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} } 

Java 8语言规范的当前草案 (第15.27.4章)

lambda表达式的值是对具有以下属性的类实例的引用:

  • 该类实现目标function接口,如果目标类型是交集类型,则实现交集的每个其他接口元素。
  • 该类声明了一个方法,该方法覆盖了函数接口supertype的抽象方法(以及潜在的其超接口的一些其他方法)。
  • 方法的参数类型,返回类型和抛出类型由接口的函数类型给出。
  • 方法的主体具有评估lambda主体的效果,如果它是一个表达式,或者执行lambda主体,如果它是一个块; 如果预期结果,则从方法返回。
  • 除了可以覆盖Object类的方法之外,该类不会覆盖上面提到的接口或接口的其他方法。

请注意,除了字节代码应该支持上面的规范之外,JLS没有说明如何编译代码。

因此,lambda表达式返回的对象

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

将是遵循上述规则的类的实例。

鉴于你的评论

 consumer.getClass() 

返回以下类

 Example$$Lambda$1/1072591677 

它似乎正在生成一个特定于lambda表达式的类似代理的类。

看这里:

  • 如何编译Java lambda函数?