将异常重新分配给catch参数

时间:2015-12-25 07:05:22

标签: java eclipse exception java-7

请考虑以下代码。

import java.io.IOException;
import java.sql.SQLException;

public class ReassignmentICatch {

    public void couldThrowAnException() throws SQLException, IOException {}
    public void rethrow() throws SQLException, IOException {
      try {
         couldThrowAnException();
         System.out.println("Did not throw");
      } catch (Exception e) {   //Line-1
        e = new IOException();  //Line-2    
        throw e;                //Line-3        
      }
    }

    public static void main(String[] args) {
        ReassignmentICatch rc = new ReassignmentICatch();
        try {
            rc.rethrow();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

据我所知,java7中的catch(Exception e)没有捕获像java6这样的所有异常,而只捕获方法couldThrowAnException声明中提到的那些异常。另外,不允许将新的异常重新分配给catch参数(e),这就是为什么我们在Line-3时出现编译错误的原因

在java6中也不允许这种重新分配。我认为应该允许在java6中重新分配,所以我在eclipse中更改了java-compiler的属性,并将合规性级别设置为1.6,以查看此代码是否编译。

我无法预测的行为是:
1.Eclipse正在给出同样的错误

  

未处理的异常类型异常

for java 6 7 and 8.

2.当我尝试使用javac -target 1.6 -source 1.6 ReassignmentICatch.java获取

时使用命令行
  

警告:[options] bootstrap类路径未设置   -source 1.6 ReassignmentICatch.java:18:错误:未报告的异常异常;必须严格或声称被抛出           

  throw e;
  ^ 1 error 1 warning 

使用java7和java8,我能够使用输出Did not throw成功编译并运行它。为什么IDE和命令行没有给出相同的结果。

有人可以告诉我这里我缺少的东西。
感谢。

3 个答案:

答案 0 :(得分:3)

我不确定Java 6和Java 7的含义在于它们如何捕获异常,因为我不知道类似的内容,您可以发布引用吗?

方法声明中提到的异常是throws clause例外。这些是方法本身无法捕获但希望它的来电者能够捕获的例外情况。

分配给catch变量时不应该出错。但是,您获得的错误是因为您正在抛出异常类型,并且未在throws子句中声明它。

考虑以下代码

e = new IOException();  //Line-2    
throw e;                //Line-3

即使您已分配e IOException个实例,e的类型仍为Exception。哪个没有捕获,也没有在throws子句中声明,因此报告为错误。

有两种解决方案。您可以在throws子句或类型转换e中声明Exception,然后再抛出它。

public void rethrow() throws SQLException, IOException
//becomes
public void rethrow() throws Exception

throw e;
//becomes
throw (IOExceptoin)e;
//or
throw new IOException();

编辑*

link中给出的Java 6和Java 7之间的区别在于Java 7能够在编译时推断异常类型。即使它被分配到超级类型,Java 7也能够推断出它的原始类型而不会抱怨。这使我们不必将异常对象包装到RuntimeException对象中。

Eclipse和命令行输出差异的原因很可能是您没有为不同的Java版本修改Eclipse中的编译器设置。在Eclipse中更改项目的Java版本时,需要更改以下

  1. 构建路径中的Java系统库
  2. 编译器源合规性(首选项> Java>编译器>编译器合规性级别)
  3. 完成两项更改后,您应该能够看到正确的行为。

答案 1 :(得分:0)

java中有两种类型的异常:已检查的异常(继承自Exception)和未经检查的异常(继承自RuntimeExceptions)。

必须在方法内部处理已检查的异常,或者声明要在方法签名中抛出异常。这就是为什么重新抛出异常仍然会给你一个编译错误。

通常通过包装到RuntimeException来重新抛出异常:

try {
    doSomething();
} catch (Exception ex) {
    throw new RuntimeException(ex);
}

查看有关Java Exceptions http://tutorials.jenkov.com/java-exception-handling/index.html

的非常好的教程

答案 2 :(得分:0)

正如java-6中的 11thdimension 所示,编译是不可能的,因为即使分配了新的IOEXception(),catch参数e的静态类型仍然是Exception因此,只能在方法声明中声明IOException来处理。在Java-7中使用异常e在catch中工作正常
例如,以下程序无法在pre-java7编译器上编译。

import java.io.IOException;

public class ExampleExceptionRethrowSE7

{
    public static void demoRethrow() throws IOException {
    try {


        throw new IOException("Error");
    }
    catch(Exception exception) {
        /*

         * Do some handling and then rethrow.
         */
        throw exception;
    }
   }

    public static void main(String[] args) {
        try {
            demoRethrow();
        }

        catch (IOException exception) {
            System.err.println(exception.getMessage());
        }
    }
}


发布代码中的throw e语句导致错误的原因是我们无法将异常重新分配给catch参数e,这与我们在multi-catch中面临的限制相同。

  

this和multi-catch之间的区别在于编译器   发生错误。对于multi-catch,编译器错误发生在该行上   我们尝试为参数分配一个新值,而在这里,   编译器错误发生在我们抛出e的行上。它是   不同,因为在Java 7之前编写的代码仍然需要编译。   由于multi-catch语法是全新的,因此没有遗留代码   担心。

PS:命令行和eclipse现在给出了相同的一致错误。我不知道之前命令行出了什么问题。 :P