Cag*_*tay 6 java lambda java-8
这里的示例代码无法在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);
}
}
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
通过JLS 15.9.2(确定封闭实例)和15.13.3(方法引用的运行时评估)阅读,我不明白为什么这应该无法编译,并且错误消息似乎完全错误,因为我可以手动构建一个Sum实例在同一方法中就好了.
我发现之前的一个问题内部类的构造函数引用在运行时看起来与VerifyError失败相关,并且那里的链接JDK问题(https://bugs.openjdk.java.net/browse/JDK-8037404)表明了一系列问题.这方面的编译问题; 也许这是一个更普遍的问题的另一个例子.不过,我不确定我是否正确阅读规范; 这可以用另一种方式工作吗?
这看起来确实像是处理本地类(方法内的类声明)的编译器错误。如果更改为内部类(将类声明移到方法之外),那么它可以正常工作。您可以同时将其更改为静态类,这会稍微减少开销。
(内部类和本地类都有对包含类的隐式引用,这意味着构造函数有一个“隐藏”的第一个参数,您可以使用 javap 看到它。我怀疑编译器知道在Sum::new使用内部类,但只是缺少对本地类执行相同操作的逻辑。)
| 归档时间: |
|
| 查看次数: |
591 次 |
| 最近记录: |