考虑以下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}
}
答案 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表达式的类似代理的类。
见这里: