代码之家  ›  专栏  ›  技术社区  ›  Mohamad Alhamoud

为什么我们不必向RuntimeException添加Try-Catch?

  •  16
  • Mohamad Alhamoud  · 技术社区  · 15 年前

    我想问一下为什么我们不需要在 RuntimeException 除了其他例外,我们应该这样做吗?

    我的意思是:

    public class Main {
        public static void main(String[] args) {
           throw new RuntimeException();
        }
    }
    

    编辑: 当我说: throw new RuntimeException(); 很明显会发生异常,那么为什么编译器不禁止呢?

    7 回复  |  直到 9 年前
        1
  •  26
  •   BalusC    15 年前

    那是因为它是一个 未检查的 例外。它不需要显式声明或捕获。也看到 Sun tutorial on the subject .

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

    如果存在应该引发运行时异常的特定情况,并且不能使用它的某个特定子类,那么应该在新异常的javadoc和调用方法(例如)中对其进行扩展并正确地记录。 ConfigurationException extends RuntimeException 如果调用代码在使用前没有正确配置应用程序/API。这应该向最终用户(另一个开发人员)发出足够的信号,以便采取相应的措施。

    简而言之: RuntimeExceptions 应该识别由代码流或配置中的错误引起的程序可恢复的问题(阅读:开发人员的错误)。选中的 Exceptions 应确定由代码控制之外的意外情况(如数据库关闭、文件I/O错误、错误的最终用户输入等)引起的可编程恢复问题。 Errors 应识别程序上不可恢复的问题(例如内存不足、初始值设定项中的异常等)。

        2
  •  3
  •   bragboy    15 年前

    让我们这样争论吧。如果nullPointerException被设计为编译时异常呢?如果这样做了,编译器必须严格检查变量是否为空。这是不可能做到的。

    public void dummyMethod(Object obj){
    
    }
    

    这里编译器无法检查obj是否可以为空。但是,在使用空指针方案时,必须引发一些错误/异常。

        3
  •  2
  •   mdma    15 年前

    RuntimeException , Error 它们的子类没有经过编译时检查——它们不是方法的正式契约的一部分。

    参见JLS中的第11章,异常,特别是11.2,异常的编译时检查。

        4
  •  2
  •   Pascal Thivent    15 年前

    根据语言规范, 非强制 编译时未检查 这意味着编译器不需要方法来捕获或指定(使用 throws )他们。属于此类别的类在本节中详细介绍 11.2 Compile-Time Checking of Exceptions JLS:

    这个 未选中的异常类 是班里的 RuntimeException 以及它的子类和类 Error 及其子类 . 所有其他异常类都是 已检查异常类 . Java API定义了一些异常类,包括检查和未检查。程序员可以声明附加的异常类,不管是选中的还是未选中的。见 §11.5 用于描述异常类层次结构和由Java API和Java虚拟机定义的一些异常类。

    所以因为 运行期异常 在未选中的异常中,编译器不会强制您处理它。如果要强制一段代码的调用方处理异常,请使用选中的异常( Exception 以外 运行期异常 都是选中的异常类)。

        5
  •  1
  •   eljenso    15 年前

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

        6
  •  1
  •   aaaaaaaaaaaa    15 年前

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

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

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

        7
  •  1
  •   mickeymoon    9 年前

    这个论坛上的大多数答案都在讨论异常层次结构,Java编译器没有捕捉到它们,但我会尝试从设计的角度来回答更多的问题,以及为什么事情可能是这样设计的。

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

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

    2. 基于可避免但已知的条件 喜欢 Integer.parseInt(String) 可以扔 NumberFormatException 如果调用方传递一个不可转换的字符串 "Hello" 但调用方可以确保在将任何字符串传递给函数之前进行适当的验证,并完全消除生成异常的可能性。一个常见的用例可能正在验证表单字段 age 在将其传递到进行转换的更深的层之前。

    3. 未知或意外情况 任何时候,某些代码行可能会在代码中引发异常,因为您犯了一些错误,并且直到在生产中爆炸后才观察到错误情况,通常是 NullPointer Reference , IndexOutOfBounds 等,如果观察到可能属于第2类。

    1类例外情况通常设计为 Checked Exceptions 因为它需要强制检查不可避免的错误条件,并强制执行它们的回退。例如,IOException是选中的异常,因为在打开文件的情况下,可能会出现很多错误(如文件可能被删除、权限等),并且预验证所有这些错误可能非常麻烦。

    第二种类型的异常通常建模为 Unchecked Exceptions 因为您可能已经准备好了预验证,而且对于已经处理好的情况,强制使用“尝试并捕获”可能会很恼人。

    一般来说,第三种类型的异常甚至不需要担心,因为您不能在应用程序代码的每个语句中意外出现错误处理。但有时您可以将一个全局处理程序放在调用堆栈中相当高的某个位置,从该位置执行几乎所有应用程序代码,并以通用方式处理它,这样您的应用程序就不会因意外错误而崩溃。

    例如,如果您正在运行一个Web应用程序,您可以配置servlet容器以发送一个通用的 500 Internal Server Error 对于应用程序中任何未处理的错误。或者,如果你运行一个独立的Java应用程序,你可以保存你的内容。 main method 在一个 try catch 阻止以防止应用程序崩溃。