Java:lambda 和方法引用有不同的执行时间吗?
代码:
@FunctionalInterface
interface VoidSupplier {
void apply() throws Exception;
}
void execute(VoidSupplier voidSupplier) {
if (voidSupplier != null) {
try {
voidSupplier.apply();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
调用execute使用lambda:
@Test
public void testLambda() {
InputStream i = null;
execute(() -> i.close()); // use lambda
System.out.println("output some message"); // will be executed
}
调用execute使用方法参考:
@Test
void testMethodReference() {
InputStream i = null;
execute(i::close); // use method reference
System.out.println("output some message"); // will not be executed
}
当使用拉姆达,execute(VoidSupplier)将执行第一,和然后执行() -> i.close()。
但使用方法参照,i::close将被执行的第一,和然后执行execute(VoidSupplier)。
为什么 lambda 和方法引用具有不同的执行时间?
回答
execute(VoidSupplier voidSupplier)是一种方法。在执行此方法之前,必须评估其参数,无论它是 lambda 表达式还是方法引用。
lambda 表达式片段:
为了评估 lambda 表达式,不需要执行 lambda 表达式主体。因此,该表达式() -> i.close()不会引发异常。只有当execute被执行,被执行时NullPointerException才会抛出voidSupplier.apply(),并且你捕获那个异常,允许System.out.println被执行。
方法参考片段:
如果您使用空引用作为方法引用的左侧,则方法引用的评估将导致NullPointerException:
JLS 15.3.3。方法参考的运行时评估:
这意味着评估i::closethrows NullPointerException,并且execute()不会执行。由于您没有捕获此异常,System.out.println因此永远不会到达您的语句。