当前位置: 首页 > 面试题库 >

操作数堆栈上的类型错误...使用jdk 8,带有匿名内部类的lambda失败,为什么?

贝滨海
2023-03-14
问题内容

运行下面的代码将导致错误消息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);
    }

但是,在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);
    }
}

编译器错误?毕竟这是抢先体验版…

(除非您具有最新的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(); }
}

这实际上导致Exception in thread "main" java.lang.VerifyError: Bad local variable type(…)Reason: Type top (current frame, locals[0]) is not assignable to reference type

进一步的研究表明,如果将参数引入method 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) {
...

你觉得怎么样? 这样可以解决问题! 一切开始顺利。即使,我们将更return A();改为return new A() {};。检查一下!

我的结论是,这是真正的 JVM错误
。看来,问题出在已加载类的堆栈上。它与方法结合使用,该方法Java用于翻译lambda表达式(http://cr.openjdk.java.net/~briangoetz/lambda/lambda-
translation.html)-
它在顶级类内部生成综合方法。看来,在lambda堆栈中引入匿名类时会损坏。可以使用上述解决方法进行修复。



 类似资料:
  • 使用在Play Framework(Java版本)应用程序中调用SOAP服务的ws-security部分时,为了支持这些构件,导致了这种混乱: 所使用的工件包括: 其中,是: 通过搜索此部分: (这意味着降级包),问题将得到解决,服务调用将成功工作。 现在我的问题是:错误在哪里?在JVM、WSS4J或游戏框架中? 播放框架版本:2.5.8 java版本“1.8.0_121” Java(TM)SE运

  • 检查我的Codename One应用程序(它已经完美地工作了一年多),我意识到它不会再启动了。当我试图在Eclipse中启动它时,我得到了以下堆栈跟踪: 线程“AWT-EventQuue-0”中的异常java.lang.VerifyError:操作数堆栈上的错误类型异常详细信息:位置:javax/摆/JScrollBar.getAccessibleContext()Ljavax/可访问性/Acce

  • 问题内容: 在此问题中用户@Holger提供了一个答案,该答案显示了匿名类的不常见用法,我并不知道。 该答案使用流,但是此问题与流无关,因为这种匿名类型构造可以在其他上下文中使用,即: 令我惊讶的是,它编译并打印了预期的输出。 注意:我很清楚,自古以来,就可以构造一个匿名内部类并按如下方式使用其成员: 但是,这不是我要问的。我的情况有所不同,因为匿名类型是通过方法链传播的。 现在,我可以想象到此功

  • 问题内容: 在进行一些基本的lambda练习时,一个看似完全相同的匿名内部类的输出给我的输出与lambda不同。 场景1 输出 2 和 2 。这里没有新内容。 但是当我这样做时: 场景2 输出 2 和 3 问题:两个输出不应该相同吗? 我想念什么吗? 为了完整起见: 方案3 输出 3 和 3 。这里也没有什么新鲜的。 更新:仍从1.8.0-b132获得相同的输出 更新#2:错误报告: https

  • 下面的代码可以工作,但我收到了SonarLint的通知,因为我在流中使用了匿名类而不是lambda表达式,我不知道如何改进下面的代码来避免通知: 代码解释:我使用java.util的属性类,不幸的是,属性的返回

  • 问题内容: 在Java 7和更高版本中,菱形通常可以像这样毫无问题地用于推断类型: 但是,它不能用于这样的匿名内部类: 为什么是这样?从逻辑上讲,在这种情况下,我绝对可以将类型推断为。做出该决定的逻辑上的理由是,实际上不能在匿名内部类上推断类型,还是出于其他原因而将其省略了? 问题答案: 在JSR-334中: 不支持将Diamond与匿名内部类一起使用,因为这样做通常需要扩展类文件签名属性以表示不