繁体   English   中英

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

[英]Why can't I handle Exception e with try / catch clause?

当我编译以下代码时,一切正常,并且输出符合预期:

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

父类型Exception()的特殊之处是我无法使用try / catch语句来处理它? 为什么IllegalArgumentException()允许我使用try / catch语句来很好地处理它。 这些就是晚上参加SCJP考试时会因失败而害怕的恐惧而保持清醒的想法。

抛出不是RuntimeException的子类的异常的方法必须声明它抛出该Exception 你必须写

String reverse(String s) throws Exception {

如果您要抛出一个Exception 完成此操作后,您可以正常尝试/捕获它。

IllegalArgumentException是未经检查的异常,因为它们是RuntimeException子类。 因此,编译器不会检查它们。 编译器会检查非RuntimeException对象(例如Exception ,这将解释您所看到的内容。

因为您正在main()捕获异常,这是调用堆栈的底部,所以我认为最好使用catch (Exception e)来覆盖所有意外catch (Exception e)

引发作为RuntimeException的子类的异常的方法不必声明在该方法之后立即引发该Exception。 这就是为什么第一个代码运行良好的原因。

但是,将异常类型更改为Non-RuntimeException时,必须使该方法引发Exception,否则将发生编译错误。 这就是第二个代码出错的原因。

其他答案涵盖了编译器为什么不满意的原因,以及您可以采取的措施。 但是我认为您真正的错误是首先抛出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 (不良)或传播Exception (更糟)。 声明为throws Exception方法就像癌症。

main方法声明为throws Exception是一个特例。 JVM基础结构通常调用主要方法,该方法旨在处理任何异常。 它只是将stacktrace打印到标准错误。 即使这样,自己处理异常可能也更整洁。 在“生产级”代码库中,您通常希望将意外的异常记录在错误日志中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM