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

查看:19
本文介绍了编译后的 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);
}

什么是Consumer消费者 = x ->System.out.print(x) 被编译成?

我知道 Lambda 不是作为匿名内部类实现的.然而 Consumer 是一个接口,因此 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打开class文件时的输出.

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 composition 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 表达式的值是对一个实例的引用具有以下属性的类:

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

  • 该类实现目标功能接口,如果目标类型是交集类型,则该交集的所有其他接口元素都会实现.
  • 该类声明了一个方法,该方法会覆盖功能接口超类型的抽象方法(以及可能覆盖其超接口的其他一些方法).
  • 方法的参数类型、返回类型和抛出类型由接口的函数类型给出.
  • 该方法的主体具有评估 lambda 主体(如果它是一个表达式)或执行 lambda 主体(如果它是一个表达式)的效果堵塞;如果需要结果,则从该方法返回.
  • 该类不覆盖上面提到的一个或多个接口的其他方法,除了它可以覆盖Object的方法类.

请注意,除了字节码应支持上述规范外,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.

看这里:

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

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