编译后的 Java 8 Lambda 表达式是什么? [英] What is a Java 8 Lambda Expression Compiled to?
问题描述
考虑以下 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
被编译成?
我知道 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屋!