[英]How do method references to local class constructors in Java 8 work?
這里的示例代碼無法在Java 8(1.8.0_40)中編譯,但在Eclipse 4.4 JDT獨立編譯器(Bundle-Version:3.10.0.v20140604-1726)中編譯並成功運行:
import java.util.Arrays;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Test method references to local class constructors.
*/
public class LocalClassTest {
public long sumOfLengths(String[] input) {
class Sum {
final long value;
Sum(long value) {
this.value = value;
}
Sum(Sum left, Sum right) {
this.value = left.value + right.value;
}
Sum add(String s) {
return new Sum(value + s.length());
}
}
return Arrays.stream(input)
.reduce(new Sum(0), Sum::add, Sum::new)
.value;
}
static String[] input =
{
"a", "ab", "abc"
};
@Test
public void localClassConstructorMethodRefs() {
assertEquals(sumOfLengths(input), 6);
}
}
javac
吐出以下錯誤消息:
Error:(32, 25) java: incompatible types: cannot infer type-variable(s) U
(argument mismatch; invalid constructor reference
cannot access constructor Sum(Sum,Sum)
an enclosing instance of type LocalClassTest is not in scope)
通過JLS 15.9.2(確定封閉實例)和15.13.3(方法引用的運行時評估)閱讀,我不明白為什么這應該無法編譯,並且錯誤消息似乎完全錯誤,因為我可以手動構建一個在同一方法中的Sum
實例就好了。
我發現之前的一個問題內部類的構造函數引用在運行時看起來與VerifyError相關失敗 ,並且那里的鏈接JDK問題( https://bugs.openjdk.java.net/browse/JDK-8037404 )表明了一系列問題。這方面的編譯問題; 也許這是一個更普遍的問題的另一個例子。 不過,我不確定我是否正確閱讀規范; 這可以用另一種方式工作嗎?
這看起來像處理本地類的編譯器錯誤(方法中的類聲明)。 如果您更改為內部類(在方法外移動類聲明),那么它可以正常工作。 您可以同時將其更改為靜態類,這將略微減少開銷。
(內部類和本地類都有一個對包含類的隱式引用,這意味着構造函數有一個“隱藏”的第一個參數,你可以用javap看到。我懷疑編譯器知道在使用Sum::new
時補償這個隱藏參數Sum::new
對於內部類來說是Sum::new
的,但是對於本地類來說,邏輯是缺少的。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.