Lambda表达式中的变量在编译时混淆

时间:2018-04-09 14:27:07

标签: java lambda java-8

我在新编译的课程上得到java.lang.VerifyError。我尝试使用-Xverify:none导致java.lang.IncompatibleClassChangeError的结果。我终于决定反编译我的编译类并得到一个非常意想不到的结果。

原始lambda源(略微改为相关部分)

// field
private final Set<MediaPoolContainerModel> currentModels = Collections.synchronizedSet(new HashSet<>());


//within method
for (final ContainerModel container : containers) {
    if (container.isMandatory()) {
        currentModels.add(container);
    }

    final Component component = createComponentForContainer(container, checkEvent -> {

        if (checkEvent.isChecked()) {
            currentModels.add(container);
        } else {
            currentModels.remove(container);
        }
        editorListener.onValueChanged(currentModels);

    });
}

EventListener接口(由lambda在这里实现)如下所示:

@FunctionalInterface
public interface EventListener<T extends Event> {
    void onEvent(T event) throws Exception;
}

现在,我真的感到惊讶。反编译的类输出:

while(var11.hasNext()) {
    ContainerModel container = (ContainerModel)var11.next();
    if (container.isMandatory()) {
        this.currentModels.add(container);
    }

    Component component = createComponentForContainer(container, (checkEvent) -> {
        if (checkEvent.isChecked()) {
            this.currentModels.add(editorListener);
        } else {
            this.currentModels.remove(editorListener);
        }

        checkEvent.onValueChanged(this.currentModels);
    });
}

您可以观察到,尽管在源代码中使用了捕获container,但它不再位于lambda中。 editorListener(其开头的类型完全不同)用于它的位置。 IncompatibleClassChangeException的原因现在很明显,因为在onValueChanged而不是checkEvent上调用了editorListener

这是一个严重的编译器错误,如果是这样,有没有人知道原因可能是什么以及如何重现?是否有错误票?我还可以采取哪些措施来调查此问题吗?或者我做了一个我刚才不知道的明显错误?

切换到匿名类确实可以防止这个问题,但我发现在使用lambda时发现这种情况的原因仍然很有趣。

使用java1.8.0_161构建

0 个答案:

没有答案