如何在java中识别已检查和未检查的异常?

Posted

技术标签:

【中文标题】如何在java中识别已检查和未检查的异常?【英文标题】:How to identify checked and unchecked exceptions in java? 【发布时间】:2011-01-26 00:17:18 【问题描述】:

在阅读异常时,我总会遇到受检异常和未受检异常,所以想知道如何区分哪个是什么?

编辑:我想知道我是否创建了任何异常类,那么我如何创建为已选中或未选中?

各有什么意义?

【问题讨论】:

【参考方案1】:

检查除java.lang.RuntimeExceptionjava.lang.Error 的子类之外的所有Throwables。正确地,在 Java 中,“异常”是 java.lang.Exception 的子类,“错误”是 java.lang.Error 的子类,java.lang.Throwable 通常不直接子类化。

程序不应该创建自己的Error 子类(尽管文档对此相当模糊)所以通常你总是创建Exceptions,如果你不想检查它,使用RuntimeException

要在运行时知道您是否有检查过的异常,您可以使用:

if(throwable instanceof Exception && !(throwable instanceof RuntimeException)) 
    // this is a checked Exception
    

已检查异常是必须在 catch 子句中处理或在方法签名中声明为抛出的异常;编译器强制执行此操作。通常,对于应该由调用代码处理的异常,使用受检异常,而未受检异常用于由编程错误导致的情况,应该通过更正代码来修复。

也就是说,Java 社区中存在很多关于在任何地方使用受检异常与未受检异常的有效性的争论——这是在此答案中深入讨论的主题方式。

编辑 2012-10-23: 为了回应 cmets(这是非常有效的),澄清一下,确定捕获的 Throwable 是否已检查需要以下内容Throwable 而不是选中的Exception

if(obj instanceof Throwable && !(obj instanceof RuntimeException) && !(obj instanceof Error)) 
    // this is a checked Throwable - i.e. Throwable, but not RuntimeException or Error
    

如果有问题的对象已知Throwable 的一个实例(例如它被捕获),则只需要上述“if”的第二部分(例如,对 Throwable 的测试是多余的)。

【讨论】:

这会遗漏从Throwable 继承但不是从Exception 继承的异常,这些异常已被检查。通常你有: 一个未检查的“异常”将满足:t instanceof Error || t instanceof Exception 其他所有 instanceof Throwable 都被检查。错误是一般意义上的异常类型。 @Bee:从某种意义上说,这是非常正确的;但是,Errors 是 Errors,而不是 Exceptions,Java 在命名上有所区别(@987654341 @ 处理是理论在实践中失败的另一种情况,但我认为,这是一个相关但单独的讨论)。也就是说,Errors 也会被检查,但在 Java 命名法中它们是错误,而不是异常;然而,错误和异常都是Throwables。根据 Java 的说法,ErrorThrowable,但不是 Exception(在英语中更普遍的是,Errors 是“例外”,但它们不是“例外”)。 没错。也就是说,我假设一个方法可以决定一个 throwable 是否是一个检查过的对象,它会为所有检查过的异常返回 true,而不仅仅是检查过的异常。也就是说,它会采用这个词的小 e 意义。我看不到一个有效的用例来排除扩展 Throwable 但不是 ExceptionError 的东西。你怎么称呼它们? @Bee:我不叫他们任何东西。我从来没有遇到过使用Throwable 的直接子类的人。顺便说一句,我已经更新了我的答案以缓解您的担忧。 @Bee:是的,这就是我最后一段的意思。【参考方案2】:

见Java Language Spec, chapter 11:

未经检查的异常类是类RuntimeException 及其子类,以及类Error 及其子类。所有其他异常类都是检查异常类。 Java API 定义了许多异常类,包括选中的和未选中的。程序员可以声明额外的异常类,包括检查的和未检查的。

您可以在运行时通过instanceof 进行检查,但我真的不知道这在哪里有用。

关于你问题的第二部分:

检查的异常表示预期的错误情况,可能在正常程序执行期间发生,因此必须始终以编程方式处理(编译器强制执行)

未经检查的异常表示由于无效输入、错误或运行时限制(例如内存)而导致的意外错误情况并表示程序的异常状态;编译器不会强迫程序员处理这些,也就是说,如果你知道它们的发生,你只需要关心它们

【讨论】:

@Christoph:当然有一整所编程学派认为“预期的错误条件”并不是真正的错误,并且看到很多语言即使没有 已检查异常的概念 它们的存在是有争议的。 Joshua Bloch,Effective Java,“优先使用状态测试方法而不是异常”。然后当然还有讨厌 GOTO 的编程学校,并认为使用检查异常进行流控制是意大利面条式的 GOTO 编程。我不支持一个阵营或另一个阵营,只是说明目前的事态:)【参考方案3】:

Error 是内部虚拟机错误,通常您无法管理它。 Exception - 你可以抓住它并处理它

选中与未选中

checked 异常由编译器检查,作为程序员,您必须使用try-catch-finallythrows 处理它 unchecked 编译器不会检查异常,但您可以选择显式管理它

IntelliJ IDEA'sType Hierarchy 工具在您想查找更多信息时很有用

【讨论】:

【参考方案4】:

如果异常类是RuntimeException 的子类,则不会对其进行检查,也不必为函数声明或捕获等。Error 异常也不必声明/捕获。你问的是这个吗?

【讨论】:

【参考方案5】:

很确定这个问题之前已经被问过并回答过,但为了它,这里很好地介绍了它:http://www.javapractices.com/topic/TopicAction.do?Id=129。

严格来说,未经检查的异常将始终扩展RuntimeException,而检查的异常则不会。提到的链接解释了何时使用。

顾名思义,调用者必须处理已检查异常,通常是处理它们 (try/catch) 或将它们向上传递到堆栈。未经检查的异常通常被认为是由调用者无法控制的元素引起的。

【讨论】:

错误也未检查,但我猜你可能会争辩说它们不是例外......【参考方案6】:
package practice;

import java.io.IOException;

class Practice

    public static void main(String args[])
    
        Exception n=new NullPointerException();
        if(n instanceof RuntimeException)
        
            System.out.println("this is a runtime(unchecked) exception");
        
        else
        
            System.out.println("this is not a compiletime(checked) exception");
        

    


【讨论】:

您能解释一下为什么这可能有助于改善您的答案吗?

以上是关于如何在java中识别已检查和未检查的异常?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 Java 中禁用检查异常?

如何在 Java 6 中捕获所有已检查的异常(在一个块中)?

java异常—检查异常(checked exception)和未检查异常(unchecked exception)

简析CWE-391:未检查的错误情况缺陷漏洞

从 ejabberd 检索聊天记录时如何识别已发送和未发送的消息?

如何使用命令行检查Java类的异常终止