这个方法给了我一个编译,我不明白为什么:
private void invokeMethods(Object instance, List<Method> methods)
throws InvocationTargetException, IllegalAccessException {
methods.forEach(method -> method.invoke(instance));
}
错误消息是:
未报告的异常 java.lang.IllegalAccessException; 必须捕获 或宣布被抛出
这没有意义:异常已经声明为抛出。
IntelliJ也无法纠正它。在意向操作中,如果我选择"向方法签名添加例外",则它不执行任何操作。
我错过了什么?(我是Java 8的新手(
这里的问题是抛出异常的是 lambda,而 forEach
中使用的 lambda 没有声明为抛出异常。请参阅使用者文档。
解决这个问题的最好方法实际上是使用老式的 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
中,这并不好......
IntelliJ也无法纠正它。在意向操作中,如果我选择"向方法签名添加例外",则它不执行任何操作。
IntelliJ 无法做到这一点的原因是因为它是 Consumer
接口的一部分,而 接口是 JDK 的一部分。IntelliJ没有办法修改它。当然,IntelliJ可以以更好的方式处理这个问题。
结论:
有时 lambda 很有用,有时旧的做事方式更好。
(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);
}