Nim*_*sky 12 java lambda java-8
运行下面的代码会导致错误消息Bad type on operand stack.
public static void main(String args[]) {
TransformService transformService = (inputs) -> {
return new ArrayList<String>(3) {{
add("one");
add("two");
add("three");
}};
};
Collection<Integer> inputs = new HashSet<Integer>(2) {{
add(5);
add(7);
}};
Collection<String> results = transformService.transform(inputs);
System.out.println(results.size());
}
public interface TransformService {
Collection<String> transform(Collection<Integer> inputs);
}
Run Code Online (Sandbox Code Playgroud)
但是,删除lamda中的双括号初始化(匿名内部类)允许代码按预期运行,为什么?以下作品:
public class SecondLambda {
public static void main(String args[]) {
TransformService transformService = (inputs) -> {
Collection<String> results = new ArrayList<String>(3);
results.add("one");
results.add("two");
results.add("three");
return results;
};
Collection<Integer> inputs = new HashSet<Integer>(2) {{
add(5);
add(7);
}};
Collection<String> results = transformService.transform(inputs);
System.out.println(results.size());
}
public interface TransformService {
Collection<String> transform(Collection<Integer> inputs);
}
}
Run Code Online (Sandbox Code Playgroud)
编译错误?毕竟它是早期的访问版本......
(除非你有最新的jdk 8 lambda下载,否则不会编译.)
看来,这个问题不仅发生在lambda返回anonymous类型的情况下,而且即使在内部构造了任何匿名类lambda.即:
public class TestLambda {
public static void main(String[] args) {
xxx();
}
static void xxx() {
Functional1 f = () -> {
Object o = new Object() { };
return new A();
};
}
static class A { }
static interface Functional1 { A func(); }
}
Run Code Online (Sandbox Code Playgroud)
这实际上导致Exception in thread "main" java.lang.VerifyError: Bad local variable type(...)Reason: Type top (current frame, locals[0]) is not assignable to reference type.
进一步的调查表明,如果我们将参数引入方法xxx,异常的原因将包含其类型.例如:
Type 'java/lang/Integer' (current frame, stack[0]) is not assignable to 'lambda/TestLambda'
这已经非常有趣了.让我们将xxx参数类型(实际上并未使用)更改为顶级类型,即TestLambda:
...
xxx(new TestLambda());
}
private static void xxx(TestLambda x) {
...
Run Code Online (Sandbox Code Playgroud)
你觉得怎么样?这解决了这个问题!一切都开始运作良好.甚至,如果我们将改变return A();来return new A() {};.检查一下!
我的结论是,这是真正的JVM错误.似乎问题是加载类的堆栈.它与方法结合Java使用,用于翻译lambda表达式(http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html) - 它在顶级类中生成合成方法.看起来,当lambda堆栈中引入匿名类时会被破坏.它可以使用上面提到的解决方法来修复.
| 归档时间: |
|
| 查看次数: |
4395 次 |
| 最近记录: |