Why is catching checked exceptions allowed for code that does not throw exceptions?

后端 未结 3 1598
夕颜
夕颜 2020-12-13 13:30

In Java, methods that throw checked exceptions (Exception or its subtypes - IOException, InterruptedException, etc) must declare throws sta

3条回答
  •  一生所求
    2020-12-13 13:37

    The issue here is that checked/unchecked exception limitations affect what your code is allowed to throw, not what it's allowed to catch. While you can still catch any type of Exception, the only ones you're allowed to actually throw again are unchecked ones. (This is why casting your unchecked exception into a checked exception breaks your code.)

    Catching an unchecked exception with Exception is valid, because unchecked exceptions (a.k.a. RuntimeExceptions) are a subclass of Exception, and it follows standard polymorphism rules; it doesn't turn the caught exception into an Exception, just as storing a String in an Object doesn't turn the String into an Object. Polymorphism means that a variable that can hold an Object can hold anything derived from Object (such as a String). Likewise, as Exception is the superclass of all exception types, a variable of type Exception can hold any class derived from Exception, without turning the object into an Exception. Consider this:

    import java.lang.*;
    // ...
    public String iReturnAString() { return "Consider this!"; }
    // ...
    Object o = iReturnAString();
    

    Despite the variable's type being Object, o still stores a String, does it not? Likewise, in your code:

    try {
        safeMethod();
    } catch (Exception e) { // catching checked exception
        throw e; // so I can throw... a checked Exception?
    }
    

    What this means is actually "catch anything compatible with class Exception (i.e. Exception and anything derived from it)." Similar logic is used in other languages, as well; for example, in C++, catching a std::exception will also catch std::runtime_error, std::logic_error, std::bad_alloc, any properly-defined user-created exceptions, and so on, because they all derive from std::exception.

    tl;dr: You're not catching checked exceptions, you're catching any exceptions. The exception only becomes a checked exception if you cast it into a checked exception type.

提交回复
热议问题