将异常重新分配给 catch 参数
Reassignment of an Exception to the catch parameter
考虑以下代码。
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 给出了同样的错误
Unhandled exception type Exception
对于 java 6 7 和 8。
2.When 我正在尝试使用命令行 javac -target 1.6 -source 1.6 ReassignmentICatch.java
得到
warning: [options] bootstrap class path not set in conjunction with
-source 1.6 ReassignmentICatch.java:18: error: unreported exception Exception; must be caugh t or declared to be thrown
throw e;
^ 1 error 1 warning
并且使用 java7 和 java8 我能够编译并且 运行 它成功地输出 Did not throw
。为什么 IDE 和命令行没有给出相同的结果。
有人可以告诉我我在这里缺少什么吗?
谢谢。
java中有两种异常:已检查异常(继承自Exception)和未检查异常(继承自RuntimeExceptions)。
已检查的异常必须在方法内部处理或在方法签名中声明为抛出。这就是为什么重新抛出异常仍然会给你一个编译错误。
通常重新抛出异常是通过包装到 RuntimeException 中来完成的:
try {
doSomething();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
查看关于 Java 异常的非常好的教程 http://tutorials.jenkov.com/java-exception-handling/index.html
我不确定你说的 Java 6 和 Java 7 在捕获异常的方式上是不同的,因为我不知道类似的事情,你能post 参考 ?
方法声明中提到的异常是throws clause
个异常。这些是方法本身不捕获但希望它的调用者捕获的异常。
分配给 catch 变量时不应该出现错误。但是,您遇到的错误是因为您抛出了异常类型,而它未在 throws 子句中声明。
考虑下面的代码
e = new IOException(); //Line-2
throw e; //Line-3
即使您分配了 e
IOException
个实例,e
的类型仍然是 Exception
。哪个没有被捕获,也没有在 throws 子句中声明,因此报告为错误。
有两种解决方法。您可以在 throws 子句中声明 Exception 或在抛出之前进行类型转换 e
。
public void rethrow() throws SQLException, IOException
//becomes
public void rethrow() throws Exception
或
throw e;
//becomes
throw (IOExceptoin)e;
//or
throw new IOException();
编辑*
Java 6 和 Java 7 之间的区别,如您在 link 中给出的那样,Java 7 能够在编译时推断异常类型。即使它被分配给一个超级 class 类型 Java 7 也能推断出它的原始类型而不是不会抱怨。这使我们不必将异常对象包装到 RuntimeException
对象中。
Eclipse 和命令行输出不同的最可能原因是您没有针对不同 Java 版本修改 Eclipse 中的编译器设置。在 Eclipse 中更改项目的 Java 版本时,您需要更改以下内容
- Java 构建路径中的系统库
- 编译器源代码合规性(首选项>Java>编译器>编译器合规性级别)
完成这两项更改后,您应该能够看到正确的行为。
正如11thdimension在java中所建议的-6编译是不可能的,因为catch参数e
的静态类型仍然是Exception
即使将新的 IOEXception() 分配给 e,也不能仅通过在方法声明中声明 IOException 来处理。在 Java-7 中,在 catch 中使用 Exception e 可以正常工作
例如,以下程序无法在 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 中面临的限制相同。
The difference between this and multi- catch is where the compiler
error occurs. For multi-catch, the compiler error occurs on the line
where we attempt to assign a new value to the parameter, whereas here,
the compiler error occurs on the line where we throw e. It is
different because code written prior to Java 7 still needs to compile.
Since the multi- catch syntax is brand new, there is no legacy code to
worry about.
PS:命令行和 Eclipse 现在给出相同的一致错误。我不知道命令行前面出了什么问题。 :P
考虑以下代码。
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 给出了同样的错误
Unhandled exception type Exception
对于 java 6 7 和 8。
2.When 我正在尝试使用命令行 javac -target 1.6 -source 1.6 ReassignmentICatch.java
得到
warning: [options] bootstrap class path not set in conjunction with -source 1.6 ReassignmentICatch.java:18: error: unreported exception Exception; must be caugh t or declared to be thrown
throw e; ^ 1 error 1 warning
并且使用 java7 和 java8 我能够编译并且 运行 它成功地输出 Did not throw
。为什么 IDE 和命令行没有给出相同的结果。
有人可以告诉我我在这里缺少什么吗?
谢谢。
java中有两种异常:已检查异常(继承自Exception)和未检查异常(继承自RuntimeExceptions)。
已检查的异常必须在方法内部处理或在方法签名中声明为抛出。这就是为什么重新抛出异常仍然会给你一个编译错误。
通常重新抛出异常是通过包装到 RuntimeException 中来完成的:
try {
doSomething();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
查看关于 Java 异常的非常好的教程 http://tutorials.jenkov.com/java-exception-handling/index.html
我不确定你说的 Java 6 和 Java 7 在捕获异常的方式上是不同的,因为我不知道类似的事情,你能post 参考 ?
方法声明中提到的异常是throws clause
个异常。这些是方法本身不捕获但希望它的调用者捕获的异常。
分配给 catch 变量时不应该出现错误。但是,您遇到的错误是因为您抛出了异常类型,而它未在 throws 子句中声明。
考虑下面的代码
e = new IOException(); //Line-2
throw e; //Line-3
即使您分配了 e
IOException
个实例,e
的类型仍然是 Exception
。哪个没有被捕获,也没有在 throws 子句中声明,因此报告为错误。
有两种解决方法。您可以在 throws 子句中声明 Exception 或在抛出之前进行类型转换 e
。
public void rethrow() throws SQLException, IOException
//becomes
public void rethrow() throws Exception
或
throw e;
//becomes
throw (IOExceptoin)e;
//or
throw new IOException();
编辑*
Java 6 和 Java 7 之间的区别,如您在 link 中给出的那样,Java 7 能够在编译时推断异常类型。即使它被分配给一个超级 class 类型 Java 7 也能推断出它的原始类型而不是不会抱怨。这使我们不必将异常对象包装到 RuntimeException
对象中。
Eclipse 和命令行输出不同的最可能原因是您没有针对不同 Java 版本修改 Eclipse 中的编译器设置。在 Eclipse 中更改项目的 Java 版本时,您需要更改以下内容
- Java 构建路径中的系统库
- 编译器源代码合规性(首选项>Java>编译器>编译器合规性级别)
完成这两项更改后,您应该能够看到正确的行为。
正如11thdimension在java中所建议的-6编译是不可能的,因为catch参数e
的静态类型仍然是Exception
即使将新的 IOEXception() 分配给 e,也不能仅通过在方法声明中声明 IOException 来处理。在 Java-7 中,在 catch 中使用 Exception e 可以正常工作
例如,以下程序无法在 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 中面临的限制相同。
The difference between this and multi- catch is where the compiler error occurs. For multi-catch, the compiler error occurs on the line where we attempt to assign a new value to the parameter, whereas here, the compiler error occurs on the line where we throw e. It is different because code written prior to Java 7 still needs to compile. Since the multi- catch syntax is brand new, there is no legacy code to worry about.
PS:命令行和 Eclipse 现在给出相同的一致错误。我不知道命令行前面出了什么问题。 :P