由于未声明异常,编译失败,即使它已声明

时间:2014-12-21 22:02:21

标签: java java-8

这个方法给了我一个汇编,我不明白为什么:

private void invokeMethods(Object instance, List<Method> methods)
        throws InvocationTargetException, IllegalAccessException {
    methods.forEach(method -> method.invoke(instance));
}

错误消息是:

  

未报告的异常java.lang.IllegalAccessException;必须抓住   或宣布被抛出

这没有意义:已经宣布异常被抛出。

IntelliJ也无法纠正它。在意图操作中,如果我选择为方法签名添加例外,它就什么都不做。

我错过了什么? (我是Java 8的新手)

2 个答案:

答案 0 :(得分:13)

这里的问题是抛出异常的 lambda ,并且forEach中使用的lambda未声明抛出异常。请参阅Consumer文档。

解决这个问题的最佳方法是使用老式的for-each循环:

for (Method method : methods) {
    method.invoke(instance);
}

虽然可以使用这样的东西:

methods.forEach(method -> {
        try {
            method.invoke(instance);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
});

在我看来它并没有真正帮助你,因为你不能再从lambda中抛出完全相同的异常了,你必须将它包装在RuntimeException中,这不是很好...... < / p>

  

IntelliJ也无法纠正它。在意图操作中,如果我选择“向方法签名添加例外”,则不会执行任何操作。

IntelliJ无法做到这一点的原因是因为它是Consumer接口的一部分,它是JDK的一部分。 IntelliJ没有办法修改它。当然,IntelliJ可以更好地处理这个问题。

结论:

有时候,lambdas很有用,有时旧的做事方式会更好。

答案 1 :(得分:0)

(method -> method.invoke(instance))是lambda表达式,此表达式可以抛出IllegalAccessException | InvocationTargetException,您可以将其包围在try/catch

   methods.forEach(method -> {
            try {
                method.invoke(instance);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace(); // or throw new RuntimeException(e);
            }
        });

如果你不想在lambda中处理异常,那么只需使用

for (Method method : methods) {
        method.invoke(method);
    }