繁体   English   中英

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

[英]Why does type inference fail for lambda, but succeed for equivalent method reference?

我正在使用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
{
}

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

UPDATE

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

// 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);

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

来自JLS§15.13.2

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

lambda表达式引发错误,因为没有指定类型参数。 这会导致T被编译为Shape (如你的文章中所述),因为没有什么可以帮助推断出参数的类型。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM