[英]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.