代码之家  ›  专栏  ›  技术社区  ›  C. Ross trotttrotttrott

为什么Java既有已检查的异常,也有未检查的异常?[副本]

  •  4
  • C. Ross trotttrotttrott  · 技术社区  · 16 年前

    可能重复:
    When to choose checked and unchecked exceptions

    为什么 JAVA 作为一种语言 二者都 检查和取消检查 exceptions

    笔记

    6 回复  |  直到 8 年前
        1
  •  15
  •   MetroidFan2002    16 年前

    检查异常的理论很简单。

    在设计接口时,请考虑在方法调用的正常状态下可能发生和将发生的异常情况。在接口中声明这些异常,因为程序员必须直接处理它们。

    任何时候、任何地方都会发生IOException,Java的IO库中的流会出错。但是,这是一个已检查的异常。但是,通常情况下,您只能记录错误发生的情况——如果您只是在向控制台写入,那么如果您在向控制台写入时突然收到IOException,您可以合理地期望您做什么?

    但还有更多。

    SQLException也是这样。异常名称应显示调用它们时发生的情况。SQLException没有。在处理数据库时,每当遇到任何可能数量的错误时,都会抛出SQLException,其中大多数错误与SQL无关。

    因此,程序员通常对处理异常感到厌烦,并让Eclipse(或他们使用的任何IDE)生成如下块:

    try {
    thisMethodThrowsACheckedExceptionButIDontCare();
    }
    catch(Exception e) {
    e.printStackTrace();
    }
    

    但是,对于运行时异常,这些异常会故意冒泡,并最终由JVM或容器级别处理。这是一件好事-它会强制显示错误,然后您必须直接修复代码,而不是忽略异常-您仍然可能只打印堆栈跟踪(希望将其记录下来,而不是直接打印到控制台),但接下来会有一个异常处理程序,您被迫编写它是因为一个真正的问题,而不是因为一个方法说它 可以 可能会引发异常,但它确实引发了异常。

    Spring使用DataAccessException包装SQLExceptions,这样您就不必将它们作为选中的异常处理。因此,它使代码更加干净—如果您希望出现DataAccessException,您可以处理它—但大多数情况下,您会让它传播并记录为错误,因为您的SQL应该在发布应用程序时进行调试,这意味着DataAccessException可能是一个您无法解决的硬件问题-DataAccessException是一个比SQLException更有意义的名称,因为它表明对数据的访问失败-而不是您的SQL查询必然出错。

        2
  •  5
  •   Alexander Kjäll    16 年前

    必须 他们觉得程序员不应该处理的问题。

    例如,一个程序处理来自用户的错误输入可能是合理的,但如果底层操作系统出现问题,线程开始无缘无故地死亡,那么程序就不应该处理这些问题。

        3
  •  5
  •   Kevin Montrose    16 年前

    我个人认为,检查异常在Java中是一个错误。

    除此之外,指定已检查和未检查的异常允许库区分可恢复和不可恢复的错误。通过使所有可恢复的错误抛出已检查的异常,库/语言可以迫使开发人员处理他们可能会忽略的边缘情况。

    try{
      myCode();
    }catch(Exception e){ //Do nothing }
    

    此外,在大多数情况下,最好是举手并在出现异常时传递异常。通过强制声明已检查的异常,一个真正不关心是否发生错误的方法最终会产生依赖关系(就兼容性而言,但也包括代码气味和其他方面而言),它确实不应该这样做。

        4
  •  4
  •   Colin Goudie    16 年前

    我认为Sun最初认为这是一个好主意,因为程序员被迫处理异常。然而,许多年后,几乎所有人都同意它们是一个不好的、不必要的补充。

        5
  •  4
  •   Nick Holt    16 年前

    检查和未检查的异常引发了一点宗教争论——Java站在了篱笆的一边,C#站在了另一边。

    在Java中,当调用代码可以从错误中恢复时,应该使用选中的异常,就像在出现严重错误时使用未选中的异常一样(可能会出现异常,没有双关语) NullPointerException )调用代码不太可能从中恢复。

    就我个人而言,我喜欢将这两种方法都提供给我,因为它们允许我强制调用代码来处理开发人员可能忽略的错误情况(尽管臭名昭著的空catch块端会对此进行处理)。

        6
  •  1
  •   corlettk    16 年前

    此外,“捕获或声明”需求也不适合接口。

    我的基本想法是:“出错的东西”有两种基本味道:可恢复的和不可恢复的。。。因此:业务异常和系统错误。

    例如:对于从调用SomeStream.close()的失败中恢复,您(库开发人员)希望我(应用程序程序员)做什么?是的,我确实需要知道出了什么严重的问题,但实际上我唯一的选择是终止程序/请求/进程/线程。我甚至不可能试图从这种情况中恢复过来。。。因此,我不应该被迫写一篇文章 大量 具有高度代表性的样板文件捕获块,它们不能在调用堆栈的每个级别(可能非常深)处理该问题。因此,我相信,如果从未发明过像IOException这样的“全包”检查异常会更好。。。“CloseException扩展UncheckedIOException更合适,IMHO。”。

    此外,如果我有一台时间机器,我会回到过去,向爪哇诸神祈求:

    • 接口可丢弃
      • 抽象类异常
        • 抽象类CheckedException
        • 抽象类取消选中异常
      • 类错误

    另外:我希望看到@FaultBarrier类注释,它使编译器强制执行:所有异常(尤其是未检查的异常)都必须捕获或显式抛出。我所研究过的系统中最可怕的一块是充斥着原始运行时异常的悸动;这足以让你哭泣。