为什么我们不必将run-catch添加到RuntimeException?

时间:2010-05-01 16:13:59

标签: java exception

我想问为什么我们不必将{-1}}添加到try {catch}块中,而我们应该在其他例外情况下这样做?

我的意思是:

RuntimeException

编辑: 当我说:public class Main { public static void main(String[] args) { throw new RuntimeException(); } } 时很明显会发生异常,为什么编译器不禁止这样做?

7 个答案:

答案 0 :(得分:30)

那是因为它是未经检查的例外。它不需要显式声明或捕获。另请参阅Sun tutorial on the subject

更新:一般来说,你应该只抛出RuntimeException(最好是javadoc中列出的subclasses之一)来表示调用者做错了。即传递null参数(然后抛出NullPointerException)或非法参数(然后抛出IllegalArgumentException),或者在错误的时刻/状态调用该方法(然后抛出IllegalStateException }),等等。调用者应该修复他们的代码以避免这种情况。例如。事先检查参数是否为null,或者参数的格式/语法是否正确,或确保在适当的时刻调用该方法。

如果存在应该抛出运行时异常并且不能使用其特定子类之一的特定情况,那么您应该扩展它并在新异常的javadoc和调用方法中正确记录它,例如: ConfigurationException extends RuntimeException表示调用代码在使用前未正确配置应用程序/ API。这应该足以表明最终用户(另一个开发人员)采取相应的行动。

简而言之:RuntimeExceptions应该识别由代码流或配置中的错误引起的可编程恢复问题(读取:开发人员的错误)。 Checked Exceptions应该识别程序可恢复的问题,这些问题是由代码控制之外的意外情况引起的(例如数据库关闭,文件I / O错误,错误的最终用户输入等)。 Errors应该以编程方式识别不可恢复的问题(例如,内存不足,初始化程序内的异常等)。

答案 1 :(得分:3)

让我们这样说吧。如果NullPointerException被设计为编译时异常怎么办?如果这样做,编译器必须严格检查变量是否为null。无法做到这一点。

public void dummyMethod(Object obj){

}

这里编译器无法检查obj是否为null。但是,当您有一个空指针场景时,必须抛出一些错误/异常。

答案 2 :(得分:2)

RuntimeExceptionError及其子类特别没有经过编译时检查 - 它们不是该方法的正式合同的一部分。

参见JLS中的第11章,例外情况,特别是11.2,例外的编译时检查。

答案 3 :(得分:2)

根据语言规范,未经检查的异常 未在编译时检查,这意味着编译器不需要捕获或指定方法(使用{{1他们。属于此类别的类详见JLS的11.2 Compile-Time Checking of Exceptions部分:

  

未经检查的例外类是类throws及其子类,类RuntimeException及其子类。所有其他异常类都是已检查的异常类。 Java API定义了许多异常类,包括已检查和未选中的异常类。程序员可以声明其他检查和未检查的异常类。有关异常类层次结构的描述以及Java API和Java虚拟机定义的一些异常类,请参阅§11.5

因为在未经检查的异常中有Error,编译器不会强制您处理它。如果要强制一段代码的调用者处理异常,请使用已检查的异常(除RuntimeException之外的Exception的子类都是已检查的异常类。)

答案 4 :(得分:1)

因为不禁止抛出运行时异常,也不必声明运行时异常。您的程序是一个有效的Java程序,因此编译器没有理由抱怨。

答案 5 :(得分:1)

基本上,未捕获的异常只是显示消息和终止应用程序的简写。

你为什么要这样做?在某些情况下,您可以检测到某些内容出错,某些文件未加载,api丢失,某些数据因某种原因损坏,或者其他一百万个错误。如果你没有抛出异常,应用程序可能只是在另一个点崩溃,或者在最坏的情况下,在错误升级时继续运行,这使得调试变得更加困难。

重要的是要理解一个抛出异常因为有错误,异常不是错误,它只是信使。

答案 6 :(得分:1)

这个论坛上的大多数答案一直在谈论异常层次结构和Java编译器没有捕获它们,但我会尝试从设计角度更多地回答这个问题,以及为什么事情的设计可能就像这样。

基本上,当你调用一个函数(或编写一些代码)时,可以根据三种不同的情况抛出异常:

  1. 基于不可避免的情况,例如网络不可用或文件系统上缺少某些预期文件。

  2. 基于可避免但已知的条件,如Integer.parseInt(String),如果调用者传递了NumberFormatException之类的不可转换字符串,则可以抛出"Hello",但是调用者在将任何字符串传递给函数之前,可以确保适当的验证,并完全消除产生异常的可能性。一个常见的用例可能是在网页上验证表单字段age,然后再将其传递给进行转换的更深层。

  3. 未知或意外情况任何时候某些代码行都会在您的代码中引发异常,因为您遇到了一些错误,并且在发生错误之前没有观察到错误情况在生产中,通常在NullPointer ReferenceIndexOutOfBounds等处发生,如果观察到可能属于第2类。

  4. 类别1的例外通常设计为Checked Exceptions,因为它需要强制检查不可避免的错误条件,并强制执行其后备。例如IOException被检查异常,因为如果你打开一个文件,可能会有很多可能出错的东西(比如文件可能被删除,权限等),并且预先验证所有这些可能非常麻烦。 / p>

    第二种类型的异常通常被建模为Unchecked Exceptions,因为您可能已经进行了预先验证,并且在您已经处理过的情况下被强制使用try和catch可能会令人恼火。

    第三种类型的异常通常不必担心,因为您不能在每个可能意外出现的应用程序代码语句中放入错误处理。但有时你可以放置一个全局处理程序,在调用堆栈的某个地方,几乎所有应用程序代码都被执行,并以通用方式处理它,这样你的应用程序就不会因意外错误而崩溃。

    例如,如果您正在运行Web应用程序,则可以将Servlet容器配置为针对应用程序中的任何未处理错误发送通用500 Internal Server Error。或者,如果您运行的是独立的Java应用程序,则可以将main method的内容保留在try catch块中,以防止应用程序崩溃。