ОК, поэтому перегрузка метода - это плохое дело и торговля;. Теперь, когда это было разрешено, допустим, что я действительно хочу перегрузить метод следующим образом:
static void run(Consumer<Integer> consumer) {
System.out.println("consumer");
}
static void run(Function<Integer, Integer> function) {
System.out.println("function");
}
В Java 7 я мог легко их прозвать с помощью несимметричных анонимных классов в качестве аргументов:
run(new Consumer<Integer>() {
public void accept(Integer integer) {}
});
run(new Function<Integer, Integer>() {
public Integer apply(Integer o) { return 1; }
});
Теперь в Java 8 я хотел бы назвать эти методы с лямбда-выражениями, и я могу!
// Consumer
run((Integer i) -> {});
// Function
run((Integer i) -> 1);
Поскольку компилятор должен иметь возможность вывести Integer
, почему бы мне не оставить Integer
, а??
// Consumer
run(i -> {});
// Function
run(i -> 1);
Но это не компилируется. Компилятор (javac, jdk1.8.0_05) не нравится:
Test.java:63: error: reference to run is ambiguous
run(i -> {});
^
both method run(Consumer<Integer>) in Test and
method run(Function<Integer,Integer>) in Test match
Мне, интуитивно, это не имеет смысла. Абсолютно никакой двусмысленности между выражением лямбда, которое дает возвращаемое значение ( "совместимое с оценкой" ) и лямбда-выражение, которое дает void
( "void-compatible" ), как указано в JLS §15.27.
Но, конечно же, JLS является глубоким и сложным, и мы наследуем 20-летнюю историю совместимости с обратной совместимостью, и есть такие новые вещи, как:
Определенные выражения аргументов, содержащие неявно типизированные лямбда-выражения (§15.27.1) или ссылки на неточные методы (§15.13.1) игнорируются критериями применимости, поскольку их значение не может быть определено до тех пор, пока не будет выбран целевой тип.
Вышеуказанное ограничение, вероятно, связано с тем, что JEP 101 не было реализовано полностью, как можно видеть здесь и здесь.
Вопрос:
Кто может сказать мне, какие именно части JLS задают эту неоднозначность времени компиляции (или это ошибка компилятора)?
Бонус: почему все было так решено?
Обновление:
С помощью jdk1.8.0_40 выше компилируется и работает отлично