【问题标题】:When should checked exception/unchecked exception be chosen?什么时候应该选择已检查异常/未检查异常?
【发布时间】:2012-03-30 17:19:39
【问题描述】:

我从各种教程中了解到“如果可以合理地期望客户端从异常中恢复,则将其设为受检异常。如果客户端无法从异常中恢复,则将其设为未受检异常。”

我很想通过一些代码示例来看看前面语句的有效性。 例如

try {
        br.readLine();
    } catch (IOException e) {

        e.printStackTrace();
    }

这里,IOException被检查了Exception。那么,当这个异常发生时我应该如何恢复呢?在这里,我排除了异常记录,异常重新抛出任务,因为它们实际上并没有恢复,即使事情正确。那么,这里应该应用什么修改来恢复呢?

如果有办法从中恢复,那么同样的方法可以应用于以下代码:

 try{
    Integer.parseInt("ghg4");
 }catch(NumberFormatException nfe){   
   }

这里的 NumberFormatException 是一个运行时/未经检查的异常。所以如果有办法从中恢复,那么为什么首先将它声明为运行时异常?

【问题讨论】:

标签: java exception compiler-construction coding-style checked


【解决方案1】:

我看到了三种类型的异常。一个极端是你无能为力的,比如 NullPointerException。您将在代码中以非常高的级别处理此问题,或者根本不处理。检查它会很荒谬。

另一端是提供有意义信息的那些。当方法已经有返回值时,它们是一种返回值的方式,有时是一种复杂的方式。它们也是跳上调用堆栈的一种简单方法。 (我可以写一本关于这方面的书,但我会在这里停下来。) EOFException 应该 就是一个很好的例子。文件有其目的,您迟早会遇到它,并且您不想每次阅读时都检查它。在这种情况下,需要检查异常。 (我认为 user1291492 会同意我的观点。)它可能会发生,任何调用 read 方法的人都应该为此做好准备。他们会更喜欢编译器错误而不是运行时错误。

现在,对于这种类型的异常,您想要放入堆栈跟踪!!!这需要很多时间。调用者只需要知道他遇到了 EOF,而不是在 IO 系统的深处发生了什么!此外,除非要返回有趣的信息,否则异常本身应该是 final static 引用,生成一次并用于发生的每个 EOF。

中间的第三种类型是 Java 库使用的类型,例如 real EOFException。他们没有任何意义。调用者希望永远不会得到 EOF(例如,他将自己的标记放在那里)并且 EOFException 与 NullPointerException 具有相同的性质,他希望得到它并且不需要麻烦并丢失了堆栈跟踪的处理时间。我认为问题在于 Java 设计者自己——当我想到它时我不得不承认自己也有这个问题——这很少见——不确定这些异常可能属于前两个类别中的哪一个。即使在同一个程序中,EOFException 也可能在某个地方指示程序完全失败。在另一种情况下,这可能是找出文件已被读取的正常方法。所以最终的结果是大量的异常同时完成并且做得很差,迫使程序员在他们无论如何都不能做任何事情时使用trycatchthrows,并交给他们精心制作的堆栈跟踪他们没有不需要。

补充:我应该明确指出,您可以从真正的 EOFException 中恢复,只需接受您已完成读取文件并继续,可能在 @987654326 中使用 break 语句@ 堵塞。但是,还有其他适当的方法可以捕获 EOF,因此 EOFException 通常意味着像 NullPointerException 这样的真正问题。奇怪的是,我使用 NumberFormatException 的方式,我认为它应该被检查。当我想要一个数字时得到“AAA”是很常见的,这是用户错误,而不是编程错误。

【讨论】:

    【解决方案2】:

    c# 取消了检查异常,我认为这是一个好主意。

    在我编写的代码中,我主要遵循 c# 模式,从 RuntimeException 扩展所有内容。但是,在某些地方,我利用检查的异常来强迫自己和任何使用我的代码的人对更“正常”的异常情况做出响应

    【讨论】:

    • 不认为这是一个好的、有建设性的答案吗?请说出原因
    • 丢弃 Checked 异常绝对不是一个好主意。通常它会隐藏有趣的异常,保持程序稳定的唯一解决方案是在所有调用的顶部放置一个大的 try/catch 块,从而导致无趣的反馈
    • 不同意,但既然我已经“错”了,我想我还是错了
    • @Guillaume:如果检查异常是一个好主意,那么我希望其他一些语言现在会借用这个想法,想不出有什么。有很多带有受检异常的程序在异常处理方面存在可怕的问题,我认为对受检异常的有效性存在怀疑的合理空间。
    • @Nathan 但 Java 开发人员继续使用它们。那些家伙都怎么了? ;-)
    【解决方案3】:

    RuntimeException 和 Exception 之间没有明确的界限。一般来说,过度使用 Exception 的后代会导致 catch 子句链(例如,用于反射处理代码)或只是 catch (Exception e) 不关心特定类型。有许多不同的做法,这个问题是有争议的 - 即它不是那么简单,并且没有唯一一种在您的应用程序中设计异常的正确方法。


    我遵守以下规则:

    1. 如果要单独处理异常并且可以与简单的输入数据错误或类似情况区分开来 - 它是已检查异常。

    2. 如果异常是由明显错误的输入条件或代码中的错误(如 NPE)引起的 - 那么它就是运行时异常。

    例如,根据这个逻辑,我会让 IOException 成为 RuntimeException 的后代。


    更新:关于 IOException,这不是非黑即白的。但是一些 IOE 后代(如 FileNotFoundException、MalformedURLException 等)——绝对是错误的输入。当您使用 ByteArray IO 流(或类似的流)来处理永远不会发生的 IOE 时,这也会让事情变得烦人。

    【讨论】:

    • +1,但为什么要 IOException 扩展 RuntimeException?良好的输入检查不能阻止这种情况; I/O 操作本质上是有风险的。
    • 同意。这不是非黑即白。但是一些 IOE 后代(如 FileNotFoundException、MalformedURLException 等)——绝对是错误的输入。当您使用 ByteArray IO 流(或类似的流)来处理永远不会发生的 IOE 时,这也很烦人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多