为什么类型推断对于lambda失败,但成功进行等效的方法引用?

Ste*_*ler 7 java generics lambda type-inference

我正在使用lambda在下面的Java程序中实现一个功能接口.当lambda作为参数传递给泛型方法时,编译器会标记"不兼容类型"错误,因为它推断lambda实现了Func <Shape>接口,该接口让编译器将lambda参数("thing")解释为当lambda尝试将其传递给需要Round类型参数的方法(testRound)时,为Shape类型.这个错误对我有意义.

但是等效方法引用不会引发错误消息.我一直误以为lambda和可以替换lambda的方法引用是可以互换的.在这里,事实并非如此.

public class Main
{
    public static void main(String... args)
    {
        methodB(thing -> Main.testRound(thing)); // incompatible types
        methodB(Main::testRound);                // no problem here
    }

    static <T extends Shape> void methodB(Func<T> function)
    {
    }

    static boolean testRound(Round thing)
    {
        return true;
    }
}

interface Func<T>
{
    boolean test(T ob);
}

class Shape
{
}

class Round extends Shape
{
}
Run Code Online (Sandbox Code Playgroud)

当lambda失败时,为什么方法引用成功?

UPDATE

Vince Emigh在下面找到了我已经标记为接受的答案.虽然这不是我的问题的一部分,但是有四种方法可以解决这样一个事实:Func<Shape>如果一个人真的被使用lambdas ,那么lambda只被推断为类型:

// Use a type witness.

Main.<Round>methodB(thing -> testRound(thing));

// Make the lambda's argument type explicit.

methodB((Round thing) -> testRound(thing));

// Cast the argument.

methodB(thing -> testRound((Round)thing));

// Store the lambda reference in a Func<Round> variable.

Func<Round> lambda = thing -> testRound(thing);
methodB(lambda);
Run Code Online (Sandbox Code Playgroud)

我没有看到任何理由更喜欢其中一个而不是方法参考,除非有人认为lambdas的密度稍低(并且可能更具可读性).但是,如果你想要它们,它们就在那里.

Vin*_*igh 2

来自JLS \xc2\xa715.13.2

\n\n
\n

与 lambda 表达式不同,方法引用可以与泛型函数类型(即具有类型参数的函数类型)一致。这是因为 lambda 表达式需要能够声明类型参数,但没有语法支持这一点;而对于方法引用,不需要这样的声明。

\n
\n\n

由于未指定类型参数,因此 lambda 表达式会引发错误。这会导致T编译为Shape(如您的帖子中提到的),因为没有任何东西可以帮助推断参数的类型。

\n\n

至于方法引用,由于可以从方法的参数推断类型,因此不需要显式类型参数,如上面的 JLS 语句中所述。

\n