当我编译以下代码时,一切正常,输出正如预期的那样:
class Propogate {
public static void main(String[] args) {
Propogate obj = new Propogate();
try {
obj.reverse("");
} catch (IllegalArgumentException e) {
System.out.println(e);
} finally {
System.out.println("That's all folks");
}
}
String reverse(String s) {
if(s.length() == 00) {
throw new IllegalArgumentException();
}
String reversed = "";
for(int i=s.length() - 1; i >= 0; --i) {
reversed += s.charAt(i);
}
return reversed;
}
}
计划结果:
java.lang.IllegalArgumentException
That's all folks
但是,当我运行完全相同的代码但从
更改异常类型时IllegalArgumentException to plain old exception all I get is:Propogate.java:14: error:
unreported exception Exception; must be caught or declared to be thrown
throw new Exception();
^
1 error
使用try / catch语句无法处理的父类型Exception()有什么特别之处?为什么IllegalArgumentException()允许我用try / catch语句处理它就好了。这些是一个被夜间保持清醒的想法与失败的恐惧,不,只是参加SCJP考试。
答案 0 :(得分:5)
抛出不是RuntimeException
的子类的异常的方法必须声明它抛出Exception
。你必须写
String reverse(String s) throws Exception {
如果你要用Exception
投掷它。一旦你这样做,你可以通过try / catch正常捕获它。
答案 1 :(得分:1)
IllegalArgumentException
是未经检查的例外,因为它们是RuntimeException
的子类。所以编译器不会检查它们。非RuntimeException
对象(例如Exception
)由编译器检查,这解释了您所看到的内容。
因为您在main()
中捕获了异常,这是您的调用堆栈的底部,我认为最好通过catch (Exception e)
覆盖所有意外情况。
答案 2 :(得分:1)
抛出作为RuntimeException的子类的异常的方法不必声明它抛出该方法后面的Exception。这就是第一个代码顺利进行的原因。
但是,当您将异常类型更改为Non-RuntimeException时,必须使该方法抛出异常,否则将发生编译错误。这就是第二个代码出错的原因。
答案 3 :(得分:0)
其他答案涵盖了编译器不满意的原因,以及您可以采取的措施。但我认为你真正的错误就是首先抛出Exception
。
投掷Exception
几乎总是一个坏主意。原因是,如果您的代码抛出Exception
,那么它(或其他人的代码)通常必须捕获异常。但是捕获Exception
的问题在于,您的代码还会捕获可能由您的代码抛出的Exception
的任何/所有子类型。这包括可能由代码中的错误引起的未经检查的异常,等等。
例如:
public class Test {
private static Integer a;
private static Integer b;
public static void main(String[] args) {
try {
if (a.equals(b)) {
throw Exception("they are the same");
}
System.out.println("they are different");
} catch (Exception ex) {
System.out.println(ex.message());
}
}
}
当你运行它时,你会得到神秘的输出“null”。 (为读者练习......弄清楚原因。)
将方法声明为throws Exception
更糟糕,因为现在调用者强制要么捕获Exception
(坏)要么传播它(更糟糕)。声明为throws Exception
的方法就像癌症一样。
将main
方法声明为throws Exception
是一种特殊情况。主要方法(通常)由JVM基础结构调用,旨在处理任何异常。它只是将堆栈跟踪打印到标准错误。即便如此,自己处理异常可能更为简洁。在“生产等级”代码库中,您通常希望在错误日志中记录意外异常。