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