Thread.sleep的方法引用不明确 [英] Method reference is ambiguous for Thread.sleep

查看:145
本文介绍了Thread.sleep的方法引用不明确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个奇怪的问题,其中对 Thread :: sleep 的方法引用是不明确的,但具有相同签名的方法不是。

I've come across a weird problem where a method reference to Thread::sleep is ambiguous but a method with the same signature is not.

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;
    }
}

我收到了这两个错误:

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 天然。它有什么改变吗?我不认为重载 Thread :: sleep(long,int)在这里发挥作用。为什么会这样?

The only difference I see is that Thread::sleep is native. Does it change anything? I don't think the overload Thread::sleep(long, int) comes into play here. Why does it happen?

编辑:使用javac版本1.8.0_111

Using javac version 1.8.0_111

推荐答案

您可以通过添加方法 sleep 来重新创建您自己类中的问题,其中包含两个类Test的参数,如下所示:

You can recreate the problem in your own class by adding a method sleep with two arguments to class Test like below:

public static void sleep(long millis) {
}

public static void sleep(long millis, int nanos) {
}

所以这个问题实际上是由于方法sleep被重载引起的。

So the problem is really caused by the fact that the method sleep is overloaded.

JLS表示初始方法选择代码只查看功能接口的类型参数的数量 - 仅在第二阶段它会查看内部方法的签名功能界面。

The JLS indicates that the initial method selection code only looks at the number of type arguments to the functional interface - only in the second phase does it look at the signature of the method inside the functional interface.


无法指定要匹配的特定签名ed,
例如,Arrays :: sort(int [])。相反,函数接口
提供了用作重载
分辨率算法(第15.12.2节)的输入的参数类型。

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)可能与功能界面 FooVoid< P> 匹配,而重载 void sleep(long,int)可能匹配功能接口 Foo< P,R> 。这就是为什么你得到引用foo是模糊的错误。

So in the case of Thread::sleep, void sleep(long) potentially matches functional interface FooVoid<P>, while overload void sleep(long, int) potentially matches functional interface Foo<P, R>. That's why you get the "reference to foo is ambiguous" error.

当它试图进一步看看如何匹配 Foo< P时, R> 使用函数方法 R调用(P param1)到方法 void sleep(long,int),它发现这实际上是不可能的,并且你得到另一个编译错误:

When it tries to go further and see how to match Foo<P, R> with functional method R call(P param1) to the method void sleep(long, int), it finds out that this is not actually possible, and you get another compile error:

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)

这篇关于Thread.sleep的方法引用不明确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆