是的,调用已经成为一个规范的“测试”习语,因为预期是一个廉价的内在操作,并且,我想,如果结果不使用,HotSpot可能能够检测到这种模式并将操作简化为固有的检查操作。getClass()
null
getClass()
null
getClass()
另一个示例是创建一个内部类实例,其外部实例不是:this
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
}
另请参阅 JDK-8073550:
我们类库中的一些地方使用了使用 object.getClass() 检查空性的奇怪技巧。虽然这似乎是一个明智的举动,但它实际上使人们感到困惑,认为这是一种批准的空检查做法。
在 JDK 7 中,我们有 Objects.requireNonNull,它提供了适当的空值检查,并正确地声明了意图。
这是否也应该适用于编程语言内部检查可能是有争议的,因为为此目的使用会创建对包外部的类的依赖关系,而这些类在源代码中不可见。在这种特定情况下,只有那些查看字节码的人才能看到这个技巧。但是已经决定用Java 9改变这种行为。Objects.requireNonNull
java.lang
以下是编译同一测试类的方式:jdk1.9.0b160
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
}