为什么这个Java 8 lambda无法编译?

2022-08-31 11:48:27

以下 Java 代码无法编译:

@FunctionalInterface
private interface BiConsumer<A, B> {
    void accept(A a, B b);
}

private static void takeBiConsumer(BiConsumer<String, String> bc) { }

public static void main(String[] args) {
    takeBiConsumer((String s1, String s2) -> new String("hi")); // OK
    takeBiConsumer((String s1, String s2) -> "hi"); // Error
}

编译器报告:

Error:(31, 58) java: incompatible types: bad return type in lambda expression
    java.lang.String cannot be converted to void

奇怪的是,标记为“OK”的行编译良好,但标记为“Error”的行失败。它们似乎基本相同。


答案 1

您的 lambda 需要与 一致。如果您参考 JLS #15.27.3(Lambda 的类型):BiConsumer<String, String>

如果满足以下所有条件,则 lambda 表达式与函数类型一致:

  • [...]
  • 如果函数类型的结果是 void,则 lambda 主体要么是语句表达式 (§14.8),要么是与 void 兼容的块。

因此,lambda 必须是语句表达式或 void 兼容块:


答案 2

基本上,是一段可执行的代码,它实际上做了一些事情(它创建一个新的字符串,然后返回它)。返回的值可以忽略,并且仍可以在 void-return lambda 中使用以创建新的字符串。new String("hi")new String("hi")

但是,它只是一个常量,它本身不会做任何事情。在 lambda 主体中处理它的唯一合理方法是返回它。但是 lambda 方法必须有返回类型 或 ,但它返回 ,因此出现错误。"hi"StringObjectvoidString cannot be casted to void