【问题标题】:Re-throw an InvocationTargetException target exception重新抛出 InvocationTargetException 目标异常
【发布时间】:2012-04-18 17:17:32
【问题描述】:

如何重新抛出 InvocationTargetException 的目标异常。我有一个方法,它使用反射在我的一个类中调用 invoke() 方法。但是,如果在我的代码中抛出异常,我不关心 InvocationTargetException,只需要目标异常。这是一个例子:

public static Object executeViewComponent(String name, Component c,
        HttpServletRequest request) throws Exception {

    try {
        return c.getClass()
                .getMethod(c.getMetaData().getMethod(), HttpServletRequest.class)
                .invoke(c, request);
    } catch (InvocationTargetException e) {
        // throw the target exception here
    }
}

我面临的主要问题是调用 throw e.getCause();不会抛出异常,而是抛出 Throwable。也许我的处理方法不正确?

【问题讨论】:

    标签: java exception-handling invocationtargetexception


    【解决方案1】:

    您可以在不明确声明的情况下重新提出原因。

    public static Object executeViewComponent(String name, Component c,
            HttpServletRequest request) throw /* known exceptions */ {
    
        try {
            return c.getClass()
                    .getMethod(c.getMetaData().getMethod(), HttpServletRequest.class)
                    .invoke(c, request);
        } catch (InvocationTargetException e) {
            // rethrow any exception.
            Thread.currentThread().stop(e.getCause());
        }
    }
    

    【讨论】:

    • 它有效,但很危险。 stop() 方法已被弃用是有充分理由的。这是来自 stop() API 文档:已弃用此方法本质上是不安全的。有关详细信息,请参见 stop()。这种方法的另一个危险是它可能被用来生成目标线程没有准备好处理的异常(包括线程不可能抛出的检查异常,如果不是这种方法的话)。有关详细信息,请参阅为什么不推荐使用 Thread.stop、Thread.suspend 和 Thread.resume?。
    【解决方案2】:
    catch (InvocationTargetException e) {
        if (e.getCause() instanceof Exception) {
            throw (Exception) e.getCause();
        }
        else {
            // decide what you want to do. The cause is probably an error, or it's null.
        }
    }
    

    【讨论】:

    • 你怎么会有 null 导致 InvocationTargetException 的原因?
    • 我认为 Method.invoke() 抛出这个异常不会是原因,但是 InvocationTargetException 有一个允许空目标的构造函数,所以在其他情况下,它可能是无效的。从 Method.invoke API 文档中,我不确定是否将错误包装在按原样抛出的 InvocationTargetException 中。
    • 这项工作很棒!我没有意识到我可以将原因转换为异常并抛出它。谢谢!
    • 小心,有时getCause()为空,异常在getTargetException()中
    【解决方案3】:

    以下内容很冗长,但我喜欢避免反思和强制转换。我不认为(但不确定)Java 7 的 multi catch 语法会有用。

    public static Object executeViewComponent(String name, Component c,
            HttpServletRequest request) throw KnownException_1 , KnownException_2 , ... , KnownException_n {
    
        try {
            return c.getClass()
                    .getMethod(c.getMetaData().getMethod(), HttpServletRequest.class)
                    .invoke(c, request);
        }
        catch ( InvocationTargetException cause )
        {
              assert cause . getCause ( ) != null : "Null Cause" ;
              try
              {
                   throw cause . getCause ( ) ;
              }
              catch ( KnownException_1 c )
              {
                    throw c
              }
              catch ( KnownException_2 c )
              {
                    throw c
              }
              ...
              catch ( KnownException_n c )
              {
                    throw c
              }
              catch ( RuntimeException c )
              {
                    throw c ;
              }
              catch ( Error c )
              {
                    throw c ;
              }
              catch ( Throwable c )
              {
                    assert false : "Unknown Cause" ;
              }
        }
    }
    

    【讨论】:

      【解决方案4】:

      Exception#getCause 返回一个Throwable。如果您希望编译器认为您正在抛出 Exception,那么您可能需要强制转换它。

      throw (Exception) e.getCause();
      

      【讨论】:

        【解决方案5】:

        您可以使用 throw 关键字和您捕获的相应对象重新抛出您之前捕获的任何异常:

        catch (XXXException e)
        {
               throw e;
        }
        

        【讨论】:

        • OP 想要 InvocationTargetException 的原因
        • 这只是抛出相同的异常。我想“吃掉” InvocationTargetException 并且只抛出目标异常。
        • 那么你必须这样做: throw (Exception) e.getCause(); (就像蒂姆·本德所说的)
        猜你喜欢
        • 1970-01-01
        • 2011-10-10
        • 1970-01-01
        • 2012-06-29
        • 1970-01-01
        • 2023-02-22
        • 2011-06-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多