如果您查看字节码
Consumer<String> println = System.out::println;
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
该getClass()
方法被调用的System.out
,结果被忽略。
这是间接的空引用检查吗?
当然,如果您跑步
PrintStream out = null;
Consumer<String> println = out::println;
这将触发NullPointerException。
是的,调用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提供正确的null检查,并正确声明意图。
这是否也应适用于编程语言固有检查可能是值得商,的,因为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
}
问题内容: 本地类的Java文档说: 此外,局部类可以访问局部变量。但是,局部类只能访问声明为final的局部变量。当局部类访问封闭块的局部变量或参数时,它将捕获该变量或参数。例如,PhoneNumber构造函数可以访问局部变量numberLength,因为它被声明为final。numberLength是捕获的变量。 捕获的变量是什么,其用途是什么,为什么需要它?请帮助我理解它的概念。 问题答案:
大概是这样的: 谢谢[已解决] 也感谢Umer Farooq的回答:从lambda内部修改局部变量
如问题所示,值可变的lambda捕获不适用于常量 但是为什么对不可变的lambda也这样做呢?在不可变lambda中,声明为,因此它无论如何都不能修改捕获的值。 当我们移动lambda时,这种情况的坏后果就会发生,例如,当我们将lambda包装在一个中时。 请参见以下两个示例: 我们得到以下编译器生成的lambda类: 程序打印以下内容(使用gcc或clang): 在第一个示例中,至少复制了三次值
问题内容: 在有效的Java(第275页)中,有以下代码段: 捕获中断异常以重新引发它有什么用?为什么不让它飞呢? 问题答案: 简单的答案是,这是一个检查的异常,它不在方法(或方法)的签名中。所以你必须抓住它。一旦发现它,建议您设置为设置中断标志。除非您确实打算压缩中断。
问题内容: 我试图理解Java中捕获变量的概念。 我发现了有关它的详细文章:http : //www.devcodenote.com/2015/04/variable-capture-in- java.html 我不确定字节码部分: 类似地,为了访问封闭方法的局部变量,将创建变量的隐藏副本,并将其保留在内部类 文件 中,该 文件 从该变量访问该变量。 当最终原始值在编译时未知时,如何将其保存到类文
例如: 但是你可以在块之前声明它,然后它就可以正常工作了: 我只是想知道这样做的设计原因。为什么在块中创建的对象不在方法其余部分的范围内?也许我没有深入了解除了只是观察抛出的之外是如何工作的。