Unknown Region

プログラムでハマったエラーとその解決方法についての備忘録メモ

【Java】Lambda式で「ambiguous(あいまい)」になるケースについて

ちょっとハマったのでメモ。

java.util.Functionjava.util.ConsumerなどのFunctionalInterfaceなクラスのインスタンスを引数に取るメソッドに対して、Lambda式を与えるとambiguous(あいまい)」としてコンパイルエラーになるケースが存在する。

例えば以下のクラスはコンパイルエラーになる。

例: Demo1.java

import java.util.function.Consumer;
import java.util.function.Function;

public class Demo {
  public static void main(String... args) {
    doHoge(e -> {
      throw new RuntimeException();
    });
  }

  public static void doHoge(Function<Object, Object> function) {
    System.out.println("function");
  }

  public static void doHoge(Consumer<Object> consumer) {
    System.out.println("consumer");
  }
}

これはthrow戻りが関係していて、Lambda式をjava.util.Functionとして解釈すべきかjava.util.Consumerとして解釈すべきか分からなくなってしまうため。

これはFunctionalInterfaceとして用意されたメソッドの引数や返り値の型が被っているクラス(例えばjava.util.Function<Object, Boolean>java.util.Predicate<Object>など)をoverloadとして作成した場合も発生する。

また返り値が存在するメソッドを使用する場合に、ブロック及びreturnを省略した場合もコンパイルエラーになる。

例: Demo2.java

import java.util.function.Consumer;
import java.util.function.Function;

public class Demo2 {
  public static void main(String... args) {
    doHoge(e -> System.getProperties());
  }

  public static void doHoge(Function<Object, Object> function) {
    System.out.println("function");
  }

  public static void doHoge(Consumer<Object> consumer) {
    System.out.println("consumer");
  }
}

 

これらの問題の解決方法としては、明確にreturnを書いてやるかLambda式にキャストを追加してやれば良い。

(当たり前だがoverloadの型被りの場合はreturnでは解決しない)

例: Demo3.java

import java.util.function.Consumer;
import java.util.function.Function;
public class Demo3 {
  public static void main(String... args) {
    try {
      doHoge((Function<Object, Object>) e -> { // Functionとして認識される
        throw new RuntimeException();
      });
    } catch (RuntimeException ignore) {
    }
    try {
      doHoge((Consumer<Object>) e -> { // Consumerとして認識される
        throw new RuntimeException();
      });
    } catch (RuntimeException ignore) {
    }
    doHoge(e -> { // Functionとして認識される
      return System.getProperties();
    });
    doHoge(e -> { // Consumerとして認識される
      System.getProperties();
    });
  }

  public static void doHoge(Function<Object, Object> function) {
    System.out.println("function");
  }

  public static void doHoge(Consumer<Object> consumer) {
    System.out.println("consumer");
  }
}

実行結果: Demo3.java

function
consumer
function
consumer

 

連絡先: plugout777★yahoo.co.jp (クローラー対策のため★を@に変更してください)