1. ホーム
  2. java

[解決済み] このJava 8のラムダは、なぜコンパイルに失敗するのでしょうか?

2023-06-09 16:37: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" と書かれた行は失敗することです。 これらは本質的に同じように見えます。

どのように解決するのですか?

と一致するラムダである必要があります。 BiConsumer<String, String> . を参考にすると JLS #15.27.3 (ラムダの型) :

<ブロッククオート

ラムダ式は、以下の全てが真であれば、関数型と合同である。

  • [...]
  • 関数型の結果がvoidの場合、ラムダ本体はステートメント式(§14.8)かvoid互換ブロックのどちらかになります。

つまり、ラムダはステートメント式かvoid互換ブロックのどちらかでなければなりません。

  • コンストラクタの呼び出しは ステートメント式 であるため、コンパイルされます。
  • 文字列リテラルはステートメント式ではないので、void互換ではありません(cf. の例では、15.27.2 の例を参照)ので、コンパイルされません。