请考虑以下代码。
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和命令行没有给出相同的结果。
有人可以告诉我这里我缺少的东西。
感谢。
答案 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 :(得分: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