java - Thread.sleep 的方法引用不明确

标签 java java-8 functional-interface

我遇到了一个奇怪的问题,其中对 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::sleepnative。它有什么改变吗?我不认为重载 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/

相关文章:

java - 在运行时从配置文件/数据库/属性文件解析并创建消息

java - Java 8 中 parallelStream 的变异减少

lambda - 自定义功能接口(interface)汇总统计

java - 如何使用OpenCV绘制具有正确旋转角度的boundingRect?

java - Hibernate mysql 测试

java - jtable tablecellrenderer 不执行任何操作

java-8 - Java 8 - 具有嵌套对象的比较器

java - 限制一个流,看看是否有挂起的元素

java - 通用 Java 函数 - 返回通用值

lambda - 如何在 Kotlin 中将 Lambda 传递给 toSortedSet()