2017-10-28 46 views
0

考虑以下方案:与Java SE 6(和以前的版本),更精确的重新抛出异常

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" 
      } 
    } 
} 

此错误只是与Java SE 6(或以前的版本)是因为,首先,当我们建立“catch”块(catch(Exception ex)),由ex指定的异常对象的类型为FirstException(或SecondException)。但是,当ex被重新抛出(throw ex),Java编译器执行如下3项任务:

  1. 版本 “EX” 系统。
  2. 初始化新的异常对象,“EX”,其具有异常的类型
  3. 掷“EX” - 这是异常的情况下,现在,不是FirstException(或SecondException)实例

因此,在Java SE 6中,我们不能使用“更精确地重新抛出异常”,因为下面的原因。但是,在Java SE 7(或更高版本)中,我们可以这样做,因为当我们重新抛出ex时,运行时系统不会释放并初始化新对象ex。它会检查(找到)ex1 come from (the try block above), and so know that ex is an instance of FirstException or SecondException`。

我上面的解释是否正确?

+0

我不能说这是你的解释和哪部分是问题。 –

+0

我*能*告诉你,“为什么我可以在Java 7或更高版本上编译这个,但不是Java 6或更低版本”(如果的确如此)与* runtime *行为没有任何关系。这将与*编译器*有关,因为它已经变得更加智能。 –

+0

这是真的在Java> 6编译?它看起来像一个不好的做法..编辑:它,我看到这个例子来自Java文档[链接](https://docs.oracle.com/javase/7/docs/technotes/guides/language/追赶multiple.html)。 – NickL

回答

2

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

在Java 6-,捕捉到的异常的类型被声明为Exceptioncatch块,所以这是编译器的想法被抛出。

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

+0

我不明白,当我检查“ex”的类型(使用instanceof)时,我得到“FirstException”。因此,“ex”具有FirstException类型,为什么当我们重新运行时,运行时系统会抛出Exception类型,而它是FirstException? –

+0

@John'instanceof'是一个* runtime *的东西。该错误是*编译时*的事情。编译器很愚蠢。它没有推断出什么是可能的,它只是看它被声明为什么。在这种情况下,Java 7+稍微聪明一点。 – Bohemian

+0

我可以总结一下:“在Java SE 6-中,编译器并不关心在重新抛出之前发生的所有事情,所以,当”ex“被重新抛出时,编译器会抛出异常(它看起来是什么声明为”ex“),虽然实际上,“ex”是FirstException ...是对的吗? –