我會讓它變得簡單。
為什么下面的代碼會編譯:
final int[] arr = { 1, 2, 3, 4 };
final Supplier<Integer> summer = () ->
{
int temp = 0;
for (int i : arr) { temp = i; }
return temp;
};
final int sum = summer.get();
但是下面的代碼片段沒有?
final int[] arr = { 1, 2, 3, 4 };
final int sum = (() ->
{
int temp = 0;
for (int i : arr) { temp = i; }
return temp;
}).get();
錯誤資訊:
SupplierTest.java:8: error: lambda expression not expected here
final int sum = (() ->
^
1 error
error: compilation failed
uj5u.com熱心網友回復:
您需要一個目標型別來識別 lambda 正在實作的類。否則,無法知道您是在宣告 aSupplier還是說 a Callable。但是如果你想避免這個變數,你可以使用強制轉換:
final int[] arr = { 1, 2, 3, 4 };
final int sum = ((IntSupplier)() ->
{
int temp = 0;
for (int i : arr) { temp = i; }
return temp;
}).getAsInt();
也就是說,我希望這是一個理論練習。幾乎沒有理由在實際代碼中使用它。
uj5u.com熱心網友回復:
Lambda 運算式是所謂的poly-expressions,這意味著它們對它們出現的背景關系很敏感。
Java 中的 Lambda本身沒有型別,編譯器總是需要根據以下任何一個來推斷它們的型別:
- 分配背景關系;
- 呼叫背景關系;
- 鑄造背景關系。
這是Java 語言規范 §15.27 中的引述。Lambda 運算式
如果lambda 運算式出現在程式中的賦值背景關系(第 5.2 節)、呼叫背景關系(第 5.3 節)或強制轉換背景關系(第 5.5 節)之外的某個地方,則這是一個編譯時錯誤。
您的第一個片段是出現在Assignment context中的 lambda 運算式的示例,即左側指定的型別告訴該 lambda 符合的目標函式介面應該是什么:
final Supplier<Integer> summer = () ->
{
int temp = 0;
for (int i : arr) { temp = i; }
return temp;
};
同時,在您的第二個片段中,沒有編譯,因為無法推斷 lambda 運算式的型別。
可以在@shmosel 的答案中觀察到Casting 背景關系的示例。
下面是如何通過呼叫背景關系提供目標型別的說明:
final int[] arr = {1, 2, 3, 4};
final int sum = foo(() -> {
int temp = 0;
for (int i : arr) temp = i;
return temp;
});
你foo()可以使用:
public static <T> T foo(Supplier<T> supplier) {
return supplier.get();
}
或者:
public static int get(IntSupplier supplier) {
return supplier.getAsInt();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/531996.html
