在Java Lambda';这就是为什么对捕获的变量调用getClass()

在Java Lambda';这就是为什么对捕获的变量调用getClass(),java,lambda,java-8,javac,bytecode,Java,Lambda,Java 8,Javac,Bytecode,如果你看一下 Consumer<String> println = System.out::println; 正在对系统.out调用getClass()方法,结果被忽略 这是间接空引用检查吗 当然,如果你跑的话 PrintStream out = null; Consumer<String> println = out::println; PrintStream out=null; 消费者println=out::println; 这会触发NullPointerEx

如果你看一下

Consumer<String> println = System.out::println;
正在对
系统.out
调用
getClass()
方法,结果被忽略

这是间接空引用检查吗

当然,如果你跑的话

PrintStream out = null;
Consumer<String> println = out::println;
PrintStream out=null;
消费者println=out::println;

这会触发NullPointerException。

是的,调用
getClass()
已经成为一种规范的“测试
null
”习惯用法,因为
getClass()
被认为是一种廉价的内在操作,我想,如果未使用
getClass()
的结果,HotSpot可能能够检测此模式并将操作减少为内在的
null
-check操作

另一个例子是创建一个内部类实例,而外部实例不是
this

public class ImplicitNullChecks {
    class Inner {}
    void createInner(ImplicitNullChecks obj) {
        obj.new Inner();
    }

    void lambda(Object o) {
        Supplier<String> s=o::toString;
    }
}

谢谢你,你的见解一如既往地很有价值。如果只需要一条空校验字节码指令就好了。@David Conrad:这并不经常需要,而且专用校验指令相对于一条调用指令(对于一个众所周知的方法)的优势并没有那么大。作为一个净好处,如果JVM识别
对象.requirennull
并从本质上处理这些调用,那么显式调用它的Java代码也会从中受益。@holi Java:我不确定,您希望使用哪种外部引用。每个人都可以验证讨论过的编译表单,例如,使用,引用的
JDK-8073550
已经链接,如果您想更深入,您可以从讨论开始并遵循讨论。@Lii我注意到已经覆盖了它。不幸的是,除非此功能专门处理
Objects.requirennoull
并分析调用者,否则它在这里没有帮助。
outer.new Inner()
示例就在这里,在我的回答中;这个问题肯定让我高兴。
public class ImplicitNullChecks {
    class Inner {}
    void createInner(ImplicitNullChecks obj) {
        obj.new Inner();
    }

    void lambda(Object o) {
        Supplier<String> s=o::toString;
    }
}
Compiled from "ImplicitNullChecks.java"
public class bytecodetests.ImplicitNullChecks {
  public bytecodetests.ImplicitNullChecks();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  void createInner(bytecodetests.ImplicitNullChecks);
    Code:
       0: new           #23                 // class bytecodetests/ImplicitNullChecks$Inner
       3: dup
       4: aload_1
       5: dup
       6: invokevirtual #24                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
       9: pop
      10: invokespecial #25                 // Method bytecodetests/ImplicitNullChecks$Inner."<init>":(Lbytecodetests/ImplicitNullChecks;)V
      13: pop
      14: return

  void lambda(java.lang.Object);
    Code:
       0: aload_1
       1: dup
       2: invokevirtual #24                 // Method java/lang/Object.getClass:()Ljava/lang/Class;
       5: pop
       6: invokedynamic #26,  0             // InvokeDynamic #0:get:(Ljava/lang/Object;)Ljava/util/function/Supplier;
      11: astore_2
      12: return
}
Compiled from "ImplicitNullChecks.java"
public class bytecodetests.ImplicitNullChecks {
  public bytecodetests.ImplicitNullChecks();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  void createInner(bytecodetests.ImplicitNullChecks);
    Code:
       0: new           #26                 // class bytecodetests/ImplicitNullChecks$Inner
       3: dup
       4: aload_1
       5: dup
       6: invokestatic  #27                 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
       9: pop
      10: invokespecial #28                 // Method bytecodetests/ImplicitNullChecks$Inner."<init>":(Lbytecodetests/ImplicitNullChecks;)V
      13: pop
      14: return

  void lambda(java.lang.Object);
    Code:
       0: aload_1
       1: dup
       2: invokestatic  #27                 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
       5: pop
       6: invokedynamic #29,  0             // InvokeDynamic #0:get:(Ljava/lang/Object;)Ljava/util/function/Supplier;
      11: astore_2
      12: return
}