为什么我不能用try / catch子句处理Exception e?

时间:2013-12-12 00:37:25

标签: java exception-handling scjp throwable

当我编译以下代码时,一切正常,输出正如预期的那样:

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考试。

4 个答案:

答案 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基础结构调用,旨在处理任何异常。它只是将堆栈跟踪打印到标准错误。即便如此,自己处理异常可能更为简洁。在“生产等级”代码库中,您通常希望在错误日志中记录意外异常。