编译后的 Java 8 Lambda 表达式是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21858482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is a Java 8 Lambda Expression Compiled to?
提问by ams
Consider the following Java 8 snippet.
考虑以下 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);
}
What is Consumer<Integer> consumer = x -> System.out.print(x)
getting compiled to?
什么是Consumer<Integer> 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.
我知道 Lambda 不是作为匿名内部类实现的。然而Consumer<Integer>
,接口因此x -> System.out.print(x)
必须产生某种对象,但不清楚正在产生什么样的对象。
Is there some new type of object in Java 8 to represent a lambda expression?
Java 8 中是否有一些新类型的对象来表示 lambda 表达式?
UpdateHere 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.
更新这是反编译的程序,该程序是用 eclipse java 8 编译器编译的,下面的输出来自 eclipse 打开类文件时。
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);
看起来 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 lambdax -> System.out.print(x);
(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}
}
采纳答案by Sotirios Delimanolis
The current draft of the Java 8 Language Specificationstates (chapter 15.27.4)
Java 8 语言规范的当前草案状态(第 15.27.4 章)
The value of a lambda expression is a reference to an instance of a class with the following properties:
- 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.
lambda 表达式的值是对具有以下属性的类实例的引用:
- 该类实现目标功能接口,如果目标类型是交集类型,则实现交集的所有其他接口元素。
- 该类声明了一个方法,该方法覆盖功能接口超类型的抽象方法(以及可能覆盖其超接口的一些其他方法)。
- 方法的参数类型、返回类型和抛出类型由接口的函数类型给出。
- 该方法的主体具有评估 lambda 主体(如果它是一个表达式)或执行 lambda 主体(如果它是一个块)的效果;如果需要结果,则从该方法返回。
- 该类不覆盖上面提到的一个或多个接口的其他方法,除了它可以覆盖
Object
该类的方法。
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.
请注意,除了字节码应支持上述规范之外,JLS 没有说明应如何编译代码。
As such, the object returned by the lambda expression
因此,由 lambda 表达式返回的对象
consumer.getClass()
will be an instance of a class that follows the above rules.
将是遵循上述规则的类的实例。
Given your comment that
鉴于你的评论
Example$$Lambda/1072591677
returns the following class
返回以下类
##代码##it seems that it is generating a proxy-like class specific for lambda expressions.
似乎它正在生成一个特定于 lambda 表达式的类似代理的类。
See here:
看这里: