什么时候编译器要求我捕获异常?

时间:2011-03-03 07:17:28

标签: java

class MyException extends Exception {
    MyException() {}
    MyException(String msg) { super(msg);}
}
public class NewException {

    static void f() throws MyException {
        System.out.println("throwing exception from f()");
        throw new ClassCastException();
    }
    static void g() throws MyException {
        System.out.println("throwing exception from g()");
        throw new MyException("parametrized ");
    }
    public static void main(String ...strings ) {
        try { 
            f();
        }
        catch(MyException e) {
            e.printStackTrace(System.out);
        }
        try {
            g();
        }
        catch(MyException e) {
            e.printStackTrace(System.out);
        }
    }
}

在函数f()中,我指定将抛出“MyException”异常,实际上我抛出了一些与MyException无关的其他异常,但编译器仍然没有抱怨。为什么呢?

2 个答案:

答案 0 :(得分:5)

ClassCastException扩展RuntimeException,这意味着它是unchecked,因此编译器不需要您处理它。

来自RuntimeException的Javadoc:

  

不需要在throws子句中声明任何方法   RuntimeException的子类   可能会在执行期间抛出   该方法但未被捕获。

答案 1 :(得分:1)

ide的答案是正确的 - 只有java.lang.Exception或子类(直接或间接)的异常被“检查”,java.lang.RuntimeException或子类的异常检查。只需要声明从方法中抛出的已检查异常(包括那些声明由您调用的方法抛出的异常,但是您没有捕获它们)。这意味着不需要声明不是Exception(令人困惑,等等)的异常,例如Error的子类。 (您也可以直接对Throwable进行子类化,但通常不应该这样做。)

来自Java语言规范,section 11.2

  

Java编程语言的编译器在编译时检查程序是否包含已检查异常的处理程序,方法是分析执行方法或构造函数可能导致的检查异常。对于每个可能结果的已检查异常,方法(第8.4.6节)或构造函数(第8.8.5节)的throws子句必须提及该异常的类或该异常类的一个超类。对异常处理程序的存在进行编译时检查旨在减少未正确处理的异常数。

     

未经检查的异常类是RuntimeException类及其子类,以及类Error及其子类。所有其他异常类都是已检查的异常类。 Java API定义了许多异常类,包括已检查和未选中的异常类。程序员可以声明其他检查和未检查的异常类。有关异常类层次结构的描述以及Java API和Java虚拟机定义的一些异常类,请参见§11.5。

     

throws子句中指定的已检查异常类是方法或构造函数的实现者和用户之间的契约的一部分。重写方法的throws子句可能没有指定此方法将抛出任何已检查的异常,其抛出的子句不允许重写的方法抛出。当涉及接口时,可以通过单个重写声明覆盖多个方法声明。在这种情况下,重写声明必须具有与所有重写声明兼容的throws子句(第9.4节)。