如果对你的Java类生成的class进行反编译的话
$ javap -l -c -s Functional.class
将会得出如下结果:
Compiled from "Functional.java"
public class debug.test.Functional {
public debug.test.Functional();
descriptor: ()V
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ldebug/test/Functional;
public static void useConsumer(java.util.function.Consumer, T);
descriptor: (Ljava/util/function/Consumer;Ljava/lang/Object;)V
Code:
0: aload_0
1: aload_1
2: invokeinterface #2, 2 // InterfaceMethod java/util/function/Consumer.accept:(Ljava/lang/Object;)V
7: aload_0
8: aload_1
9: invokeinterface #2, 2 // InterfaceMethod java/util/function/Consumer.accept:(Ljava/lang/Object;)V
14: return
LineNumberTable:
line 10: 0
line 11: 7
line 12: 14
LocalVariableTable:
Start Length Slot Name Signature
0 15 0 consumer Ljava/util/function/Consumer;
0 15 1 t Ljava/lang/Object;
public void lambadaTest_02();
descriptor: ()V
Code:
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: dup
4: invokestatic #4 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
7: pop
8: invokedynamic #5, 0 // InvokeDynamic #0:accept:(Ljava/io/PrintStream;)Ljava/util/function/Consumer;
13: ldc #6 // String Hello World!
15: invokestatic #7 // Method useConsumer:(Ljava/util/function/Consumer;Ljava/lang/Object;)V
18: return
LineNumberTable:
line 16: 0
line 17: 18
LocalVariableTable:
Start Length Slot Name Signature
0 19 0 this Ldebug/test/Functional;
}
上面最核心一条指令是invokedynamic. 这条指令允许你把System.out.println看成是Consumer接口的accept。