ちょっとハマったのでメモ。
java.util.Functionやjava.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