我遇到了一个奇怪的问题,其中对 Thread::sleep
的方法引用不明确,但具有相同签名的方法却不是。
package test;
public class Test
{
public static void main(String[] args)
{
foo(Test::sleep, 1000L); //fine
foo((FooVoid<Long>)Thread::sleep, 1000L); //fine
foo(Thread::sleep, 1000L); //error
}
public static void sleep(long millis) throws InterruptedException
{
Thread.sleep(millis);
}
public static <P, R> void foo(Foo<P, R> function, P param) {}
public static <P> void foo(FooVoid<P> function, P param) {}
@FunctionalInterface
public interface Foo<P, R> {
R call(P param1) throws Exception;
}
@FunctionalInterface
public interface FooVoid<P> {
void call(P param1) throws Exception;
}
}
我得到了这 2 个错误:
Error:(9, 17) java: reference to foo is ambiguous
both method <P,R>foo(test.Test.Foo<P,R>,P) in test.Test and method <P>foo(test.Test.FooVoid<P>,P) in test.Test match
Error:(9, 20) java: incompatible types: cannot infer type-variable(s) P,R
(argument mismatch; bad return type in method reference
void cannot be converted to R)
我看到的唯一区别是 Thread::sleep
是 native
。它有什么改变吗?我不认为重载 Thread::sleep(long, int)
在这里发挥作用。为什么会这样?
编辑:使用 javac 版本 1.8.0_111
最佳答案
您可以通过添加方法在自己的类中重现问题 sleep
类 Test 有两个参数,如下所示:
public static void sleep(long millis) {
}
public static void sleep(long millis, int nanos) {
}
所以问题真的是方法sleep被重载了造成的。
JLS 表示初始方法选择代码仅查看功能接口(interface)的类型参数的数量 - 只有在第二阶段它才会查看功能接口(interface)内部方法的签名。
JLS 15.13:
It is not possible to specify a particular signature to be matched, for example, Arrays::sort(int[]). Instead, the functional interface provides argument types that are used as input to the overload resolution algorithm (§15.12.2).
(本节倒数第二段)
所以在 Thread::sleep
的情况下, void sleep(long)
可能匹配功能接口(interface) FooVoid<P>
, 同时重载 void sleep(long, int)
可能匹配功能接口(interface) Foo<P, R>
.这就是您收到“对 foo 的引用不明确”错误的原因。
当它试图更进一步并查看如何匹配 Foo<P, R>
时用功能方法R call(P param1)
方法 void sleep(long, int)
,它发现这实际上是不可能的,你会得到另一个编译错误:
test/Test.java:7: error: incompatible types: cannot infer type-variable(s) P,R
foo(Thread::sleep, 1000L); // error
^
(argument mismatch; bad return type in method reference
void cannot be converted to R)
关于java - Thread.sleep 的方法引用不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47276988/