好吧,我试图理解和阅读可能导致它的原因,但我就是无法理解:
我的代码中有这个:
try{
..
m.invoke(testObject);
..
} catch(AssertionError e){
...
} catch(Exception e){
..
}
事情是,当它尝试调用某个方法时,它会抛出 InvocationTargetException
而不是其他一些预期的异常(特别是 ArrayIndexOutOfBoundsException
)。因为我实际上知道调用了什么方法,所以我直接进入了这个方法代码,并为假设抛出 ArrayIndexOutOfBoundsException
的行添加了一个 try-catch 块,它确实按预期抛出了 ArrayIndexOutOfBoundsException
。然而,当上升时,它以某种方式更改为 InvocationTargetException
并且在上面的代码中 catch(Exception e)
e 是 InvocationTargetException
而不是 ArrayIndexOutOfBoundsException
符合预期。
什么可能导致这种行为或者我该如何检查这种事情?
您通过使用反射调用方法添加了额外的抽象级别。反射层将任何异常包装在 InvocationTargetException
中,这样您就可以区分由反射调用失败导致的异常实际上(例如,您的参数列表可能无效)以及调用的方法中的故障。
只需解开 InvocationTargetException
中的原因,您就可以找到原始原因。
抛出异常,如果
InvocationTargetException - 如果底层方法抛出异常。
因此,如果使用反射 API 调用的方法抛出异常(例如运行时异常),反射 API 会将异常包装到 InvocationTargetException
中。
使用 InvocationTargetException
上的 getCause()
方法检索原始异常。
来自 Method.invoke() 的 Javadoc
抛出: InvocationTargetException - 如果底层方法抛出异常。
如果调用的方法抛出异常,则抛出此异常。
java.lang.reflect.Proxy
实例来扩充一个包装的对象。每个 Proxy
都使用自己的 InvocationHandler
优雅地处理特定异常(可能由包装对象引发)。对于通过此级联直到到达正确的调用处理程序/代理的异常,在每个 InvocationHandler
中,我将捕获 InvocationTargetException
,打开它,检查包装的异常是否是 instanceof
要由它处理的异常InvocationHandler
。如果它不是 instanceof
,我会抛出 unwrapped 异常...对吗?
这将打印特定方法中的确切代码行,调用该方法时引发异常:
try {
// try code
..
m.invoke(testObject);
..
} catch (InvocationTargetException e) {
// Answer:
e.getCause().printStackTrace();
} catch (Exception e) {
// generic exception handling
e.printStackTrace();
}
那个 InvocationTargetException
可能正在结束您的 ArrayIndexOutOfBoundsException
。使用反射时没有预先说明该方法会抛出什么 - 因此,与其使用 throws Exception
方法,所有异常都被捕获并包含在 InvocationTargetException
中。
This 描述类似,
InvocationTargetException 是一个已检查的异常,它包装了由调用的方法或构造函数抛出的异常。从 1.4 版开始,此异常已被改进以符合通用异常链机制。在构造时提供并通过 getTargetException() 方法访问的“目标异常”现在称为原因,可以通过 Throwable.getCause() 方法以及上述“旧方法”访问。
您可以使用 getCause() 方法与原始异常类进行比较,如下所示:
try{
...
} catch(Exception e){
if(e.getCause().getClass().equals(AssertionError.class)){
// handle your exception 1
} else {
// handle the rest of the world exception
}
}
我的 class
中的 try
/ catch
块内的外部 class
中调用记录器对象的语句出现 java.lang.reflect.InvocationTargetException
错误。
单步执行 Eclipse 调试器中的代码 &将鼠标悬停在记录器语句上,我看到记录器 object
是 null
(需要在 class
的最顶部实例化一些外部常量)。
一个问题也可能是 targetSdkVersion 已提高并且您使用了已弃用的 Gradle 清单功能。再次尝试降低 targetSdkVersion 并查看它是否有效。就我而言,它是 targetSdkVersion 31 -> 30
如果底层方法(使用反射调用的方法)抛出异常,则会抛出此异常。
因此,如果反射 API 调用的方法抛出异常(例如运行时异常),反射 API 会将异常包装到 InvocationTargetException 中。
我面临着同样的问题。我使用了 e.getCause().getCause() 然后我发现这是因为我传递了错误的参数。获取参数之一的值时出现 nullPointerException。希望这会帮助你。
调用目标异常:
我坚信任何命名约定都投入了勤奋的思想。而且,如果我们试图找到名称背后的理由,我们的问题很可能在名称中得到了答案。
让我们将名称分为 3 个部分。当“Invoking”一个“Target”方法时发生了“Exception”。并且,当通过 Java 中的 reflection 调用方法时,此包装器会引发异常。在执行该方法时,可能会引发任何类型的异常。通过设计,异常的实际原因被抽象出来,让最终用户知道异常是在基于反射的方法访问期间发生的异常。为了得到实际原因,建议捕获异常并调用ex.getCause()
。最佳实践实际上是从捕获 InvocationTargetException
的 catch 块中抛出原因
try{
method.invoke();
} catch(InvocationTargetException ite) {
throw ite.getCause();
} catch(Exception e) {
// handle non-reflection originated exceptions
throw e;
}
我知道它与其他答案相似,但我想更清楚地说明“何时”这种异常类型是由 Java 生成的,所以这对任何人来说都是一个谜。
列出 Eclipse Navigator 模式下的所有 jar 文件 验证所有 jar 文件是否处于二进制模式
在我执行 Clean->Run xDoclet->Run xPackaging 后,错误消失了。
在我的工作区,在日食中。
InvocationTargetException
中解开原因”意味着什么的人,我刚刚发现如果您使用exception.printStackTrace()
打印它,您只需查看“原因:”部分而不是顶部半/正常部分。try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }
或...catch... { throw ex.getCause() }
之类的东西you just look at the "Caused By:" section instead of the top half/normal section
+1 @HJanrs