Lambda 方法引用无效/引用不明确(javac/ecj行为差异)
使用Eclipse编译器for Java时,以下代码可以正确编译和运行Lambda 方法引用无效/引用不明确(javac/ecj行为差异),lambda,java-8,javac,type-inference,ecj,Lambda,Java 8,Javac,Type Inference,Ecj,使用Eclipse编译器for Java时,以下代码可以正确编译和运行 package org.sandbox; public final class ExceptionUtils { private ExceptionUtils(){} @FunctionalInterface public interface Runnable { void run() throws Exception; } @FunctionalInte
package org.sandbox;
public final class ExceptionUtils
{
private ExceptionUtils(){}
@FunctionalInterface
public interface Runnable
{
void run() throws Exception;
}
@FunctionalInterface
public interface Callable<T>
{
T call() throws Exception;
}
public static void uncheck( final Runnable r )
{
try
{
r.run();
}
catch( final Exception e )
{
throw new RuntimeException( e );
}
}
public static <T> T uncheck( final Callable<T> c )
{
try
{
return c.call();
}
catch( final Exception e )
{
throw new RuntimeException( e );
}
}
}
使用javac编译时,会发出以下错误:
org\sandbox\Foo.java:22: error: reference to uncheck is ambiguous
return (Foo)uncheck( super::clone );
^
both method <T>uncheck(Callable<T>) in ExceptionUtils and method uncheck(Runnable) in ExceptionUtils match
where T is a type-variable:
T extends Object declared in method <T>uncheck(Callable<T>)
org\sandbox\Foo.java:22: error: incompatible types: cannot infer type-variable(s) T
return (Foo)uncheck( super::clone );
^
(argument mismatch; invalid method reference
clone() has protected access in Object)
where T is a type-variable:
T extends Object declared in method <T>uncheck(Callable<T>)
2 errors
org\sandbox\Foo.java:22:error:uncheck的引用不明确
返回(Foo)取消选中(super::clone);
^
ExceptionUtils中的方法uncheck(可调用)和ExceptionUtils中的方法uncheck(可运行)都匹配
其中T是一个类型变量:
T扩展方法uncheck中声明的对象(可调用)
org\sandbox\Foo.java:22:错误:不兼容类型:无法推断类型变量T
返回(Foo)取消选中(super::clone);
^
(参数不匹配;方法引用无效。)
克隆()在对象中具有受保护的访问权限)
其中T是一个类型变量:
T扩展方法uncheck中声明的对象(可调用)
2个错误
这里似乎有两个问题
- 受保护的方法不能用作方法引用
- 仅基于返回类型(即T或void),无法选择正确的
方法取消选中(…)
- 是javac对方法引用限制太严格了,还是Eclipse编译器在这里太松懈了
- javac是否正确地确定了方法解析是不明确的,还是仅仅缺少Eclipse编译器的智慧来正确地确定应该选择哪个方法
return (Foo)uncheck( () -> super.clone() );
@studro,我猜无法决定调用哪个方法是原始错误的结果。如果您删除
取消选中
重载(只留下可调用的
),您在javac中仍然会有一个编译错误。我不知道有针对的错误报告。我已经把这个链接添加到了它的答案中。@Holger,它是在那个问题的同一天(10月13日)提交的。因此,它可能是由问题作者或某个路人提交的。Webbug bug后来公开出现在OpenJDK JIRA上,因为它们是手动预建模的,因此当时可能仍然不可见。我注意到了日期,并考虑了提问者提交报告的可能性。但即便如此,添加链接对未来的读者还是有价值的。你是如何注意到错误报告的?@Holger,刚刚搜索了:这个错误是目前的第三个结果。没有魔法。也许这个问题可以作为那个问题的重复来解决?
return (Foo)uncheck( () -> super.clone() );