Ответ 1
Да, вызов getClass()
стал каноническим "тестом для null
", поскольку getClass()
, как ожидается, будет дешевой внутренней операцией, и, я полагаю, HotSpot может обнаруживать этот шаблон и уменьшать если операция 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, которые обеспечивают правильную нулевую проверку и объявляют намеренно.
Это может быть спорным, нужно ли это относится к языку программирования внутренним проверкам, а также, как использование Objects.requireNonNull
для этой цели будет создать зависимость от класса за пределами java.lang
пакета не виден в исходном коде. И в этом конкретном случае трюк доступен только тем, кто смотрит на байтовый код. Но было решено изменить поведение с Java 9.
Вот как 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
}