Давайте получим функциональный интерфейс Functional
(для краткости я пропустил реализацию и упростил случай):
@FunctionalInterface
public interface Functional<E> {
void perform(E e);
default <T extends Number> void method(E e, T t) { }
default <T extends Number> void method(E e, Function<E, T> function) { }
}
И простой фрагмент кода:
Functional<String> functional = (string) -> {};
functional.method("string", (string) -> 1);
Почему метод method()
неоднозначен, поскольку в качестве параметра передается лямбда?Это должно быть легко различимо.
Eclipse :
Метод method(String, Function<String,Integer>)
неоднозначен для типа Functional<String>
Это также воспроизводится на IntelliJIdea .
Выход Javac (благодаря @ AndyTurner ):
Main.java:21: error: reference to method is ambiguous
functional.method("string", (string) -> 1);
^
both method <T#1>method(E,T#1) in Functional and method <T#2>method(E,Function<E,T#2>) in Functional match
where T#1,E,T#2 are type-variables:
T#1 extends Number declared in method <T#1>method(E,T#1)
E extends Object declared in interface Functional
T#2 extends Number declared in method <T#2>method(E,Function<E,T#2>)
и
Main.java:21: error: incompatible types: cannot infer type-variable(s) T
functional.method("string", (string) -> 1);
^
(argument mismatch; Number is not a functional interface)
where T,E are type-variables:
T extends Number declared in method <T>method(E,T)
E extends Object declared in interface Functional
Редактировать : Интересный факт.Когда я заменяю default <T extends Number>
на <T>
, это работает.T
, кажется, не может расширяться Number
, Throwable
и т. Д. *
default <T> void method(E e, T t) { }
default <T> void method(E e, Function<E, T> function) { }
Редактировать 2 : когда я задаю универсальный тип T
дляобъявление интерфейса, оно также работает:
@FunctionalInterface
public interface Functional<E, T extends Number> {
void get(E e);
default void method(E e, Function<E, T> function) { }
default void method(E e, T t) { }
}