以下代码在使用 Eclipse Compiler for Java 时可以正确编译和运行。
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 );
}
}
}
...
package org.sandbox;
import static org.sandbox.ExceptionUtils.uncheck;
public class Foo
{
private String bar;
public String getBar()
{
return bar;
}
public void setBar( final String bar )
{
this.bar = bar;
}
@Override
public Foo clone()
{
return (Foo)uncheck( super::clone );
}
}
使用 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
看来这里有两个问题
- 受保护的方法不能用作方法引用
uncheck(...)
仅根据返回类型(即 T 或 void)选择正确的方法是不可能的
总体问题是“为什么会有行为差异?”,但也许可以分解为:
- javac 对方法引用限制是否过于严格,还是 Eclipse 编译器在这里松懈?
- javac 是否正确确定方法解析不明确,或者它只是缺乏 Eclipse 编译器的智能来正确确定应该选择哪种方法?