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

时间:2014-02-18 15:40:46

标签: java lambda java-8

考虑以下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中是否有一些新类型的对象代表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<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}
}

1 个答案:

答案 0 :(得分:9)

current draft of the Java 8 Language Specification州(第15.27.4章)

  

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

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

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

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

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

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

鉴于你的评论

consumer.getClass()

返回以下类

Example$$Lambda$1/1072591677

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

见这里: