У меня есть перегруженный метод, который принимает объект Consumer и Function соответственно и возвращает общий тип, соответствующий соответствующему пользователю/функции. Я думал, что все будет хорошо, но когда я пытаюсь вызвать любой метод с помощью выражения лямбда, я получаю сообщение об ошибке, указывающее, что ссылка на метод неоднозначна.
Основываясь на моем чтении JLS §15.12.2.1. Определите потенциально применимые методы: кажется, что компилятор должен знать, что моя лямбда с блоком void соответствует методу Consumer, а моя лямбда с возвращаемым типом соответствует методу Function.
Я собрал следующий пример кода, который не удалось скомпилировать:
import java.util.function.Consumer;
import java.util.function.Function;
public class AmbiguityBug {
public static void main(String[] args) {
doStuff(getPattern(x -> System.out.println(x)));
doStuff(getPattern(x -> String.valueOf(x)));
}
static Pattern<String, String> getPattern(Function<String, String> function) {
return new Pattern<>(function);
}
static ConsumablePattern<String> getPattern(Consumer<String> consumer) {
return new ConsumablePattern<>(consumer);
}
static void doStuff(Pattern<String, String> pattern) {
String result = pattern.apply("Hello World");
System.out.println(result);
}
static void doStuff(ConsumablePattern<String> consumablePattern) {
consumablePattern.consume("Hello World");
}
public static class Pattern<T, R> {
private final Function<T, R> function;
public Pattern(Function<T, R> function) {
this.function = function;
}
public R apply(T value) {
return function.apply(value);
}
}
public static class ConsumablePattern<T> {
private final Consumer<T> consumer;
public ConsumablePattern(Consumer<T> consumer) {
this.consumer = consumer;
}
public void consume(T value) {
consumer.accept(value);
}
}
}
Я также нашел подобный пост postoverflow, который оказался ошибкой компилятора. Мой случай очень похож, хотя и немного сложнее. Для меня это все еще похоже на ошибку, но я хотел убедиться, что я не ошибаюсь в спецификации языка для лямбда. Я использую Java 8u45, который должен иметь все последние исправления.
Если я изменю свои вызовы методов, которые будут обернуты в блок, все, кажется, скомпилируется, но это добавляет дополнительную многословность, и многие автоформаторы переформатируют его на несколько строк.
doStuff(getPattern(x -> { System.out.println(x); }));
doStuff(getPattern(x -> { return String.valueOf(x); }));