【发布时间】:2021-01-09 05:47:22
【问题描述】:
我正在为 OCP 考试学习,我注意到以下 sn-p 代码,其中在 DoubleStream 上调用的 forEach 方法的参数必须与 DoubleConsumer 功能接口的参数匹配,但是 lambda 与所需的类型不匹配,为什么还能编译?
DoubleStream.of(3.14159, 2.71828)
.forEach(c -> service.submit(
() -> System.out.println(10*c)
));
DoubleConsumer(接受 Double 类型的参数,返回类型为 void),但是这个 forEach 的返回类型为 Future<?> 哪里?表示 Runnable lambda 的返回类型,它是 void,Future - 这不是 void。我这么说是因为 service.submit(...) 的返回类型是 Future<?> 它不是 void,为什么这段代码会编译?
【问题讨论】:
-
如果预期的返回类型是
void,这意味着不需要结果。 Java 也允许在此处返回任何其他内容。它会自动丢弃它。这是一种“无损”且安全的转换。 -
和独立语句
service.submit(...);一样,不给变量赋值,返回值被丢弃。如果您可以在普通语句中执行 discard,为什么不能在将 lambda 表达式映射到函数方法时呢? -
@Andreas 不,我不相信,返回类型不会被丢弃:考虑以下 lambda: () -> 5。值 5 被视为返回类型,在在上述情况下, service.submit 的返回类型被认为是 Future
的返回类型 -
消费者只需要满足
Function和Consumer都可以做到的“对流元素做某事”的约定。 -
@RamanSB 与您不能只写
5;一样,因为表达式不是语句,() -> 5对void函数方法无效。然而,() -> String.valueOf(5)是,即使它返回一个值,因为带有返回值的方法调用可以用作表达式中的语句 and。 证明:Runnable x = () -> String.valueOf(5);编译并执行得很好。valueOf()的返回值被丢弃,就像String.valueOf(5);这样的独立语句一样。可能会忽略方法返回值这一事实对于 lambdas 来说并不新鲜。
标签: java lambda concurrency return-type executor