【问题标题】:In Java, if a general exception is caught and rethrown, will outer methods still be able to catch specific exceptions?在Java中,如果捕获并重新抛出一般异常,外部方法仍然能够捕获特定异常吗?
【发布时间】:2012-01-07 03:51:58
【问题描述】:

在 Java 中,如果捕获并重新抛出一般异常,外部方法是否仍然能够捕获特定异常?

换句话说,我可以这样做吗:


try {
    try {
         //...
    } catch (Exception e) {
         //...
        throw e;
    }
} catch (SpecificException e) {
     //...
}

【问题讨论】:

    标签: java exception exception-handling try-catch rethrow


    【解决方案1】:

    重新抛出异常不会改变它的任何内容(它仍然是最初抛出的同一个对象)。

    【讨论】:

      【解决方案2】:

      虽然 jtahlborn 的回答是正确的,但还有一个优点:编译器会看到你抛出了泛型类型的异常(即使在运行时它只能是特定类的异常),并会强制你声明方法头中的通用异常。

      private void test() throws FileNotFoundException {
          try {
              throw new FileNotFoundException("Es una exception");
          } catch (IOException e) {
              throw e; <-- Error because the method only throws
                             FileNotFoundException, not IOException
          }
      }
      

      e 确实是 FileNotFoundException,但由于它被声明为 IOException,编译器可以使用更广泛的类。您可以做的是“强制”异常。

              throw (FileNotFoundException) e;
      

      【讨论】:

      • 但是,如果您要捕获多个异常,那么您将不知道将其投射到哪个异常。
      • @DougTreadwell 如果您要捕获多个异常,那么您应该真正捕获它们。这就是编译器不允许这样做的原因。
      • 然后,要么使用 instanceof 检查类型并进行适当的转换,要么坚持在方法 throws 子句中声明通用异常(在父方法中,您仍然可以检查哪个是原始异常 - 但您也必须涵盖“通用”异常,因为编译器无法确定不需要它)。无论如何,你做的太复杂了,要么调用方法必须对异常进行相同的处理(然后坚持通用的),要么它们不是(在throws中声明不同的特定异常)
      【解决方案3】:

      Eclipse 将内部捕获中的“throw e”标记为未处理的异常,但它确实捕获了异常,因为当我运行它时,它会打印“它工作!”。谢谢@jtahlborn。不幸的是,这意味着在某个地方仍然需要一个不必要的 try/catch 块。

      
      public class Tester {
      
          public static void main(String[] args) {
              try {
                  try {
                      throw new SpecificException("Test!");
                  } catch (Exception e) {
                      throw e;
                  }
              } catch (SpecificException e) {
                  System.out.println("It worked!");
              }
          }
      
      }
      

      【讨论】:

      • 这有多不幸? catch(Exception e) 将捕获从类Exception 派生的任何异常(应该是全部)。然后你重新抛出它,然后只处理一些特定的异常。 java不应该允许这样!如果您希望某个异常能够真正杀死应用程序,那么您应该使用运行时异常,因为不必捕获这些异常。
      • 异常是根据运行时类型捕获的,但编译器必须单独决定静态信息的警告和错误。当然,在您的情况下,我们仍然可以区分 catch Exception 只能 catch SpecificException 但对于任何真正的问题,这是一个难题。但无论如何,你不应该捕获比你必须捕获的更多。
      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 1970-01-01
      • 2014-08-18
      • 2010-11-06
      • 2013-10-04
      • 1970-01-01
      相关资源
      最近更新 更多