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

Java 如果throws子句只列出抛出异常的超类型,抛出异常是否保留其类型,java,exception,exception-handling,Java,Exception,Exception Handling,我有以下代码,它们分析了java异常处理的基本行为(java 7之前的版本,不尝试使用资源或多捕获或其他) 我创建了一个自定义异常层次结构来测试这个类,它位于文件的底部 public class Rethrow { public void method1() throws MyExceptionSub1 {} public void method2() throws MyExceptionSub2 { try { method1(); } catc

我有以下代码,它们分析了java异常处理的基本行为(java 7之前的版本,不尝试使用资源或多捕获或其他)

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

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 {}
我特别想知道:

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

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

这有点令人困惑

我添加了一些注释以澄清我的假设(这些假设已被编译器确认,但请告诉我我是对还是错)

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

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

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


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

Java不是一种动态类型的语言。如果使用
对象类型的参数声明方法,并向其传递
字符串类型的变量,则只有在不使用强制类型转换的情况下,才能对其调用
对象类型的方法。您可以检查变量是一个
字符串
,使用
instanceof
,将其转换为
字符串
,并调用
字符串
的方法


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

是,但“一如既往”在这里应用有点棘手。对象始终保留其动态类型,但当它传递给从方法返回的对象时,其静态类型可能会有所不同(向上转换)。throws and catch子句不是这样的,不是吗?总是这样。我不明白你为什么不这么认为,或者为什么你认为它“棘手”。这不是。另请参见