为什么捕获检查的异常允许不引发异常的代码? [英] Why is catching checked exceptions allowed for code that does not throw exceptions?

查看:513
本文介绍了为什么捕获检查的异常允许不引发异常的代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,抛出检查异常的方法(异常或其子类型 - IOException,InterruptedException等)必须声明 throws 语句:

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

public abstract int read() throws IOException;

不声明 throws 语句不能抛出异常。

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

但是,在安全方法中捕获检查的异常在java中仍然是合法的:

But catching checked exceptions in safe methods is still legal in 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?
    }
}

其实不,这有点有趣:编译器知道 e 不是一个被检查的异常并允许重新抛出它。事情甚至有点可笑,这段代码不编译:

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:

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?

返回到主要问题 - 是否有理由以这种方式实现捕获检查的异常?这只是设计中的一个缺陷,还是我缺少一些重要的因素 - 也许是后向的不兼容性?如果在这种情况下只允许使用 RuntimeException 可能会出错?

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.

推荐答案

引用 Java语言规范§11.2.3


如果一个catch子句可以捕获被检查的异常类E1,那么这是一个编译时错误,而且catch子句对应的try块不会抛出一个被检查的异常类, E1的子类或超类,除非E1是Exception或Exception的超类。

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.

我猜这个规则很久以前发生Java 7,其中多个catch不存在。因此,如果您有一个尝试块可能会引发大量异常,最简单的方法来捕获所有内容将是捕获一个常见的超类(在最坏的情况下,异常 Throwable 如果你想抓住错误 )。

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).

请注意,您可以不是捕获与实际抛出的内容完全无关的异常类型 - 在您的示例中,捕获任何子类 Throwable 这不是一个 RuntimeException 将是一个错误:

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:

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



由OP编辑: / em>答案的主要部分是问题示例仅适用于Exception类。通常,在代码的随机位置不允许检查异常。对不起,如果我使用这些例子困惑某人。


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.

这篇关于为什么捕获检查的异常允许不引发异常的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆