什么是Java 8 Lambda表达式编译? [英] What is a Java 8 Lambda Expression Compiled to?

查看:138
本文介绍了什么是Java 8 Lambda表达式编译?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下Java 8代码段。

Consider the following Java 8 snippet.

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);
}

什么是消费者<整数>消费者= x - > System.out.print(x)编译到?

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

I understand that Lambdas are not implemented as anonymous inner classes. However Consumer<Integer> is an interface therefore x -> System.out.print(x) must be producing an object of some kind but it is not clear what kind of object is being produced.

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

Is there some new type of object in Java 8 to represent a lambda expression?

更新以下是程序遵循的反编译程序eclipse java 8编译器和下面的输出是在打开类文件时来自eclipse。

Update Here is the decompiled program the program was complied with the eclipse java 8 complier and the output below is from eclipse when you open a class file.

看起来lambda表达式变成了包含lambda表达式的类的静态方法 private static synthetic void lambda $ 0( java.lang.Integer x);

It looks like that the lambda expression is getting turned into a static method on the class that contains the lambda expression 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}
}


推荐答案

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

The current draft of the Java 8 Language Specification states (chapter 15.27.4)


lambda表达式是一个ref使用具有以下属性的
类的实例:

The value of a lambda expression is a reference to an instance of a class with the following properties:


  • 该类实现目标功能接口,如果是目标type是交集类型,交集的每个其他接口元素。

  • 该类声明了一个覆盖功能接口超类型的抽象方法的方法(可能还有其超级接口的其他一些方法) 。

  • 方法的参数类型,返回类型和抛出类型由接口的函数类型给出。

  • 方法的主体具有评估效果lambda主体,如果它是一个表达式,或执行lambda主体,如果它是
    块;如果预期结果,则从方法返回。

  • 该类不会覆盖上面提到的接口或接口的其他方法,除了它可能会覆盖<$ c $的方法c>对象
    class。

  • The class implements the targeted functional interface and, if the target type is an intersection type, every other interface element of the intersection.
  • The class declares a method that overrides the functional interface supertype's abstract methods (and, potentially, some other methods of its superinterfaces).
  • The method's parameter types, return type, and thrown types are given by the interface's function type.
  • The method's body has the effect of evaluating the lambda body, if it is an expression, or of executing the lambda body, if it is a block; if a result is expected, it is returned from the method.
  • The class overrides no other methods of the interface or interfaces mentioned above, except that it may override methods of the Object class.

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

Note that the JLS doesn't say anything about how the code should be compiled except that the byte code should support the specification above.

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

As such, the object returned by the lambda expression

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

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

will be an instance of a class that follows the above rules.

鉴于您的评论

consumer.getClass()

返回以下类

Example$$Lambda$1/1072591677

它似乎正在生成代理 - 喜欢特定于lambda表达式的类。

it seems that it is generating a proxy-like class specific for lambda expressions.

见这里:

  • How will Java lambda functions be compiled?

这篇关于什么是Java 8 Lambda表达式编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆