当前位置: 首页 > 面试题库 >

为什么不捕获异常的代码允许捕获检查异常?

伍弘盛
2023-03-14
问题内容

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

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中使用安全方法捕获检查的异常仍然合法:

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 不是检查的异常,因此可以将其重新抛出。事情甚至有些荒谬,此代码无法编译:

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

第一个片段是提出问题的动机。

编译器知道不能将检查的异常抛出到安全的方法中-因此也许应该只捕获未检查的异常?

回到 主要问题 -是否有任何理由以这种方式实现捕获受检查的异常?这仅仅是设计中的缺陷,还是我缺少一些重要因素-
可能是向后不兼容?如果只RuntimeException允许在这种情况下被捕获,可能会出什么问题?例子是极大的赞赏。


问题答案:

引用Java语言规范§11.2.3:

如果catch子句可以捕获经过检查的异常类E1,则是编译时错误,并且与catch子句相对应的try块不能抛出作为E1的子类或超类的经过检查的异常类,除非E1是Exception或Exception的超类。

我猜想这个规则起源于Java 7早于Java
7,当时不存在多类别。因此,如果您有一个try可能引发大量异常的块,则捕获所有内容的最简单方法是捕获一个通用的超类(在最坏的情况下Exception,或者Throwable您也想捕获Errors)。

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

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

由OP编辑:
答案的主要部分是问题示例仅适用于Exception类的事实。通常,在代码的随机位置不允许捕获检查的异常。对不起,如果我混淆了使用这些示例的人。



 类似资料:
  • 编译器知道检查的异常不能在安全方法内抛出-所以也许它应该允许只捕获未检查的异常? 回到主要问题--有没有理由以这种方式实现捕获检查异常?这仅仅是设计中的一个缺陷还是我遗漏了一些重要的因素--也许是向后的不兼容性?在此场景中,如果只允许捕获,可能会出现什么问题?实例非常感谢。

  • 我的RMI服务器接口声明了一个方法foo(),该方法被声明为引发RemoteException和Exception,如下所示: 服务器实现为: 我的客户端在服务器上调用foo: 现在,当我运行客户端时,我得到: 从java类型的foo()中获取异常。rmi。异常异常:未声明的检查异常;嵌套的例外是:java。伊奥。InterruptedIOException:操作超时 Java文档是这样说的。rm

  • 请求(正文)

  • export class SearchService { ... .map((response) => response.json()) .catch((e) => { if (e.status >== 500) { return cachedVersion(); new Error(`${ e.status

  • 问题内容: 我正在为Android开发Java应用程序,目前遇到了一个问题,调试器正在进入catch块,并且ex为何为null?有人看过这样的东西吗? 问题答案: 这听起来像源代码,并且编译的类不同步,因此调试器正在进入错误的块。 尝试进行清理,然后进行重建。