使用JavaSE6(和以前的版本)更精确地重新抛出异常

使用JavaSE6(和以前的版本)更精确地重新抛出异常,java,exception,Java,Exception,鉴于以下计划: class FirstException extends Exception {} class SecondException extends Exception {} class RethrowException { public void rethrowMethod() throws FirstException, SecondException { boolean flag = true; try {

鉴于以下计划:

class FirstException extends Exception {}

class SecondException extends Exception {}

class RethrowException {
     public void rethrowMethod() throws FirstException, SecondException {
          boolean flag = true;
          try {
              if(flag)
                  throw new FirstException();
              else
                  throw new SecondException(); 
          }
          catch(Exception ex) {
              throw ex;   // does not compile "Unhandled exception type Exception" 
          }
     }
}
这个错误只发生在JavaSE6(或之前的版本)中,因为首先,当我们构建“catch”块(catch(Exception ex))时,由ex指定的异常对象的类型为
FirstException
(或SecondException)。但是,当重新抛出
ex
时(
throw ex
),Java编译器将执行以下3项任务:

  • 向系统释放“ex”
  • 初始化具有异常类型的新异常对象“ex”
  • 抛出“ex”-这是异常的实例,现在不是
    FirstException
    (或
    SecondException
    )的实例
  • 因此,在JavaSE6中,我们不能使用“更精确地重试异常”,原因如下。但是,在JavaSE7(或更高版本)中,我们可以这样做,因为当我们重新抛出
    ex
    时,运行时系统不会释放和初始化新对象
    ex
    。它将检查(查找)ex1的来源(上面的try块),从而知道ex
    FirstException
    SecondException`的实例


    我上面的解释是否正确?

    在Java上的任何版本中,捕获异常并从
    catch
    块抛出它都不会创建新的异常实例

    在Java6-中,捕获的异常的类型由
    catch
    块声明为
    exception
    ,因此编译器认为这就是抛出的异常类型


    在以后的版本中,异常类型被推断为仅限于可以从
    try
    块抛出的异常。

    我不知道这是您的解释的哪一部分,问题的哪一部分。我可以告诉您“为什么我可以在Java 7或更高版本上编译它,而不是Java 6或更低版本上编译它”的答案(如果确实如此)与运行时行为无关。这与编译器变得更加智能有关。这真的是在Java>6中编译的吗?对我来说,这似乎是一个糟糕的做法。编辑:是的,我看到这个示例来自Java文档。@NickL:是的,它是。编译器知道在我不明白,当我检查“ex”(使用instanceof)的类型时,我得到了“FirstException”。所以,“ex”有FirstException类型,为什么当我们重试时,运行时系统会抛出Exception类型,而它是FirstException?@John
    instanceof
    是一个运行时的东西。错误是编译时的东西。编译器很愚蠢。它没有解释什么东西可能是什么,它只看它声明的东西。Java 7+稍微聪明一点er在这种情况下。你手边有JLS参考吗?我试图找到描述这种行为的地方,但还没有找到。@ErwinBolwidt文档(OP从中获得示例)描述了这种行为()。我认为是相关的JLS部分“我们说,如果根据§11.2.1和§11.2.2中的规则,语句或表达式的执行可能导致抛出E类异常,则语句或表达式可以抛出E类异常。“@SimonForsberg,他们在Java7中添加了整个多捕获语法,我相信,这意味着编译器必须检查
    try
    块实际可能抛出的内容,并产生(或不产生)相应的错误。如果它看到
    try
    只抛出
    IOException
    ,它甚至可以从同一个catch块中重新抛出
    Throwable
    ,并且推断的异常类型被缩小为
    IOException
    ,不管如何。在某种程度上,这就是它的行为方式。