У меня есть перегруженный метод, который принимает объект Consumer и Function соответственно и возвращает общий тип, соответствующий соответствующему Consumer/Function. Я думал, что все будет хорошо, но когда я пытаюсь вызвать любой метод с лямбда-выражением, я получаю сообщение об ошибке, указывающее, что ссылка на метод неоднозначна.
Основываясь на моем прочтении JLS § 15.12.2.1. Определите потенциально применимые методы: кажется, что компилятор должен знать, что моя лямбда с пустым блоком соответствует методу 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);
}
}
}
Я также нашел похожее сообщение о stackoverflow, которое оказалось ошибкой компилятора. Мой случай очень похож, хотя немного сложнее. Для меня это все еще выглядит как ошибка, но я хотел убедиться, что не ошибаюсь в спецификации языка для лямбда-выражений. Я использую Java 8u45, в которой должны быть все последние исправления.
Если я изменю вызовы методов, чтобы они были обернуты в блок, кажется, что все компилируется, но это добавляет дополнительную многословность, и многие автоформатеры переформатируют его в несколько строк.
doStuff(getPattern(x -> { System.out.println(x); }));
doStuff(getPattern(x -> { return String.valueOf(x); }));
doStuff(getPattern((String x) -> System.out.println(x)));
doStuff(getPattern((String x) -> String.valueOf(x)));
- person Misha   schedule 02.06.2015x
меняет ситуацию. Ожидаете ли вы, что этот случай будет отображаться наFunction
:Map<String, String> map = new HashMap<>();getPattern((String x) -> map.remove(x));
? - person Tagir Valeev   schedule 02.06.2015Function
кажется более конкретным, чемConsumer
. - person Misha   schedule 02.06.2015x -> (String.valueOf(x))
для вызова метода на основеFunction
иx->{String.valueOf(x);}
для вызова метода на основеConsumer
. Но учитывая тот факт, что эти методы делают совершенно разные вещи и выдают результаты разного типа, что приводит к еще одному перегруженному выбору методов, которые снова делают совершенно разные вещи, использование одинаковых имен для этих методов является ужасной маскировкой. - person Holger   schedule 02.06.2015