為什么捕獲檢查的異常允許不拋出異常的代碼? - Why is catching checked exceptions allowed for code that does not throw exceptions? -开发者知识库

為什么捕獲檢查的異常允許不拋出異常的代碼? - Why is catching checked exceptions allowed for code that does not throw exceptions? -开发者知识库,第1张

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

在Java中,拋出已檢查異常的方法(異常或其子類型 - IOException,InterruptedException等)必須聲明throws語句:

public abstract int read() throws IOException;

Methods that do not declare throws statement can't throw checked exceptions.

不聲明throws語句的方法不能拋出已檢查的異常。

public int read() { // does not compile
    throw new IOException();
}
// Error: unreported exception java.io.IOException; must be caught or declared to be thrown

But catching checked exceptions in safe methods is still legal in java:

但是在安全方法中捕獲已檢查的異常在java中仍然是合法的:

public void safeMethod() { System.out.println("I'm safe"); }

public void test() { // method guarantees not to throw checked exceptions
    try {
        safeMethod();
    } catch (Exception e) { // catching checked exception java.lang.Exception
        throw e; // so I can throw... a checked Exception?
    }
}

Actually, no. It's a bit funny: compiler knows that e is not a checked exception and allows to rethrow it. Things are even a bit ridiculous, this code does not compile:

實際上,沒有。這有點好笑:編譯器知道e不是一個經過檢查的異常並允許重新拋出它。事情甚至有點荒謬,這段代碼不編譯:

public void test() { // guarantees not to throw checked exceptions
    try {
        safeMethod();
    } catch (Exception e) {        
        throw (Exception) e; // seriously?
    }
}
// Error: unreported exception java.lang.Exception; must be caught or declared to be thrown

The first snippet was a motivation for a question.

第一個片段是一個問題的動機。

Compiler knows that checked exceptions can't be thrown inside a safe method - so maybe it should allow to catch only unchecked exceptions?

編譯器知道檢查的異常不能被拋出一個安全的方法 - 所以也許它應該只允許捕獲未經檢查的異常?


Returning to the main question - are there any reasons to implement catching checked exceptions in this way? Is it just a flaw in the design or am I missing some important factors - maybe backward incompatibilities? What could potentially go wrong if only RuntimeException were allowed to be catched in this scenario? Examples are greatly appreciated.

回到主要問題 - 是否有任何理由以這種方式實現捕獲檢查的異常?這只是設計中的一個缺陷,還是我遺漏了一些重要因素 - 可能是落后的不兼容性?如果在這種情況下只允許捕獲RuntimeException,可能會出現什么問題?非常感謝例子。

3 个解决方案

#1


19  

Quoting the Java Language Specification, §11.2.3:

引用Java語言規范,§11.2.3:

It is a compile-time error if a catch clause can catch checked exception class E1 and it is not the case that the try block corresponding to the catch clause can throw a checked exception class that is a subclass or superclass of E1, unless E1 is Exception or a superclass of Exception.

如果catch子句可以捕獲已檢查的異常類E1並且不是對應於catch子句的try塊可以拋出作為E1的子類或超類的已檢查異常類的情況,那么這是編譯時錯誤,除非E1是異常或異常的超類。

I'm guessing that this rule originated long before Java 7, where multi-catches did not exist. Therefore, if you had a try block that could throw a multitude of exceptions, the easiest way to catch everything would be to catch a common superclass (in the worst case, Exception, or Throwable if you want to catch Errors as well).

我猜這個規則早在Java 7之前就已經存在了,而Java 7並不存在多重捕獲。因此,如果你有一個可能引發大量異常的try塊,捕獲所有內容的最簡單方法是捕獲一個共同的超類(在最壞的情況下,Exception,或者如果你想捕獲錯誤,則為Throwable)。

Note that you may not catch an exception type that is completely unrelated to what is actually thrown - in your example, catching any subclass of Throwable that is not a RuntimeException will be an error:

請注意,您可能無法捕獲與實際拋出的內容完全無關的異常類型 - 在您的示例中,捕獲不是RuntimeException的Throwable的任何子類將是一個錯誤:

try {
    System.out.println("hello");
} catch (IOException e) {  // compilation error
    e.printStackTrace();
}


Edit by OP: The main part of the answer is the fact that question examples work only for Exception class. Generally catching checked exceptions is not allowed in random places of the code. Sorry if I confused somebody using these examples.

最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复