如果throws子句仅列出抛出异常的超类型,则抛出的异常是否保留其类型

时间:2016-02-01 08:28:45

标签: java exception exception-handling

我有以下代码,它分析了java异常处理的基本行为(Java 7之前,没有try-with-resources或multi catch等)。

我创建了一个自定义异常层次结构来测试这个类,它位于文件的底部。

public class Rethrow {

  public void method1() throws MyExceptionSub1 {}

  public void method2() throws MyExceptionSub2 {
    try {
      method1();
    }
    catch (MyExceptionSubSub1 e) {}      // catch MyExceptionSub1 and all its subclasses
    catch (MyExceptionSub1 e) {}    
    //catch (MyException e) {}           // unreachable catch clause
    catch (Exception e) {}               // catch block with Exception is always reachable (by unchecked exceptions)
    throw new MyExceptionSub2();
  }

  public void method3() throws MyExceptionSub2 {
    try {
      method2();
    }
    catch (MyException e) {       // even if MyExecptionSub2 is caught by a catch block with MyException it retains its original type...
      e.printStackTrace();
      //e.method();               // ...but inside the catch block is of type MyException 
      throw e;
    }
  }

  public static void main(String... args) {
  }

}

// Custom exceptions hierarchy

class MyException extends Exception {}

class MyExceptionSub1 extends MyException {}

class MyExceptionSub2 extends MyException {

  public void method() { System.out.println("sub2"); }

}

class MyExceptionSubSub1 extends MyExceptionSub1 {}

特别是,我想知道这个:

当一个方法DECLARE抛出异常时,即使它是一个子类而不是该异常,该异常会保留其类型并被其相应的catch块捕获(这就是为什么我被赋予使用具有更多特定类型的catch块的原因比try块中的方法声明的那样?)

当在一个catch块(它的方法就像一个方法,带有exception参数和all)时,异常会保留它的类型(如果它被重新编译,编译器希望我处理或声明原始异常,即使在catch中有一个更广泛的例外)但它被视为catch参数(我不能调用catch子句中的特定方法)?

这有点令人困惑......

我添加了一些评论以澄清我的假设(由编译器确认,但请告诉我,我是对还是错)

2 个答案:

答案 0 :(得分:0)

  

当一个方法DECLARE抛出一个Exception时,即使它是一个子类而不是异常,该异常会保留其类型并被其相应的catch块捕获(这就是为什么我可以使用它)捕获具有比try块中的方法声明的更具体类型的块??

是。该对象一如既往地保留其实际类型。

  

当在catch块内部(其作用类似于方法,带有exception参数和all)时,异常保留其类型(如果重新编译,编译器希望我处理或声明原始异常,即使在内部更广泛的例外)但它被视为catch参数(我无法调用catch子句中的特定方法)?

是。参数声明一如既往地适用。

答案 1 :(得分:0)

Java不是动态类型语言。如果您声明一个类型为Object的参数的方法并向其传递String类型的变量,那么如果您不这样做,则只能在其上调用Object类型的方法使用演员表。您可以使用String检查该变量是instanceof,将其转换为String,并调用String的方法。

异常的行为方式完全相同。 catch子句使用子句中指定的类型有效地执行instanceof检查,并声明该类型的参数。存储在此参数中的实际变量可以与catch子句的参数具有不同的运行时类型。