如果你看一下字节码
Consumer<String> println = System.out::println;
Run Code Online (Sandbox Code Playgroud)
Java 8更新121生成的字节代码是
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
DUP
INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
POP
INVOKEDYNAMIC accept(Ljava/io/PrintStream;)Ljava/util/function/Consumer; [
// handle kind 0x6 : INVOKESTATIC
java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
// arguments:
(Ljava/lang/Object;)V,
// handle kind 0x5 : INVOKEVIRTUAL
java/io/PrintStream.println(Ljava/lang/String;)V,
(Ljava/lang/String;)V
]
ASTORE 1
Run Code Online (Sandbox Code Playgroud)
getClass()正在调用该方法System.out,结果被忽略.
这是间接空引用检查吗?
当然,如果你跑
PrintStream out = null;
Consumer<String> println = out::println;
Run Code Online (Sandbox Code Playgroud)
这会触发NullPointerException.
我有以下人为的代码示例。为了保持字节码较小,它没有做任何有用的事情,但希望您可以看到,通过一些更改,它会如何发挥作用。
List<String> letters = Arrays.asList("a", "b");
Stream.of(/*a, b, c, d*/).filter(letters::contains).toArray(String[]::new);
Run Code Online (Sandbox Code Playgroud)
Java 8 生成以下字节码
public Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=4, locals=2, args_size=1
start local 0 // Main this
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: iconst_2
5: anewarray #2 // class java/lang/String
8: dup
9: iconst_0
10: ldc #3 // String a
12: aastore
13: dup
14: iconst_1
15: ldc #4 // String b
17: aastore
18: invokestatic #5 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
21: astore_1
start local 1 …Run Code Online (Sandbox Code Playgroud)