Nik*_*las 12 java generics lambda exception java-8
让我们有一个功能界面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) { }
}
Run Code Online (Sandbox Code Playgroud)
还有一段简单的代码:
Functional<String> functional = (string) -> {};
functional.method("string", (string) -> 1);
Run Code Online (Sandbox Code Playgroud)
为什么方法method()不明确,因为lambda作为参数传递?这应该很容易区分.
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>)
Run Code Online (Sandbox Code Playgroud)
和
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
Run Code Online (Sandbox Code Playgroud)
编辑:一个有趣的事实.当我更换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) { }
Run Code Online (Sandbox Code Playgroud)
编辑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) { }
}
Run Code Online (Sandbox Code Playgroud)
有多个票证(此处,此处和此处)包含类似的代码片段.这些票据被解析为"不是问题",解释如下:
根据以下规则,表达式可能与目标类型兼容:
- [...]
- 如果类型变量是候选方法的类型参数,则lambda表达式或方法引用表达式可能与类型变量兼容.
因此,method在这种情况下,两种方法都可能兼容.
此外,lambda (string) -> 1与适用性无关,因为:
m除非具有以下形式之一,否则参数表达式被认为与可能适用的方法的适用性相关
- [...]
- 如果
m是泛型方法,并且方法调用不提供显式类型参数,则显式类型的lambda表达式或精确方法引用表达式,对应的目标类型(从m的签名派生)是其类型参数m.
最后:
由于
method有一个类型参数,其中lambda作为参数传递,因此从适用性检查中跳过lambda - 意味着两者都适用 - 因此存在歧义.
可能的解决方法 - 在调用方法时强制转换参数:
functional.method("string", (Function<String, Number>) (string) -> 1);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
437 次 |
| 最近记录: |