在Java中传递lambda表达式时,方法是不明确的
让我们有一个功能接口在Java中传递lambda表达式时,方法是不明确的,java,generics,exception,lambda,java-8,Java,Generics,Exception,Lambda,Java 8,让我们有一个功能接口functional(为了简洁起见,我省略了实现并简化了案例): 及 编辑2:当我对接口声明创建泛型类型T时,它也可以工作: @FunctionalInterface public interface Functional<E, T extends Number> { void get(E e); default void method(E e, Function<E, T> function) { } default
functional
(为了简洁起见,我省略了实现并简化了案例):
及
编辑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) { }
}
@functioninterface
公共接口功能{
无效获取(E);
默认的void方法(E,Function){}
默认的void方法(ee,tt){}
}
有多个票据(、和)包含类似的代码段。这些票据被视为“非问题”,解释如下:
表达式可能与相应的目标类型兼容
遵守以下规则:
- [……]
- lambda表达式或方法引用表达式可能是 如果类型变量是类型,则与类型变量兼容 候选方法的参数
method
可能是兼容的
此外,lambda(字符串)->1
与适用性无关,因为:
参数表达式被认为与参数的适用性相关
潜在适用的方法m
,除非其具有以下任一项
形式
- [……]
- 如果
是泛型方法,而方法调用不提供 显式类型参数、显式类型的lambda表达式或 对应目标的精确方法引用表达式 type(由m的签名派生)是m
的类型参数m
方法
有一个类型参数,其中lambda是
作为参数传递,lambda将从适用性检查中跳过
-这意味着两者都适用——因此存在歧义
可能的解决方法-调用方法时强制转换参数:
functional.method("string", (Function<String, Number>) (string) -> 1);
functional.method(“字符串”,(函数)(字符串)->1);
我希望
可以工作,而
会失败,因为它可以与任何参数兼容。有趣的是,情况正好相反。对于记录,如果第二种方法具有扩展数字
。@shmosel函数
严格小于对象
,但是数字
和函数
是“绑定”的,则没有区别。(并且可能有一个类扩展数字
并实现函数
)@LouisWasserman这样的类永远无法实现/实例化为lambda。当您从变量函数
引用lambda时,它似乎也能工作。奇怪的是,它无法正确推断内联时使用哪种方法。有趣的是,提供显式类型参数可以消除歧义,即functional.method(“string”,(string)->1)代码>工作正常。
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> void method(E e, T t) { }
default <T> void method(E e, Function<E, T> function) { }
@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) { }
}
functional.method("string", (Function<String, Number>) (string) -> 1);