【问题标题】:What are checked exceptions in Java/C#?Java/C# 中的检查异常是什么?
【发布时间】:2012-03-11 10:00:06
【问题描述】:

我是一名 C# 开发人员,偶尔使用 Java 编写代码。有人可以简单地解释一下 Java 中的检查异常是什么,为什么需要它?在 C# 中没有遇到过这个术语。

【问题讨论】:

标签: c# java exception


【解决方案1】:

已检查异常是编译器要求您以某种方式处理的异常。

在 Java 中,已检查的异常是 Throwables,它们不是 RuntimeExceptionError 或其子类之一。

Java 设计人员认为他们需要确保程序处理合理可能的异常。一个经典的例子是IOException。任何时候程序执行 I/O,都有可能失败。磁盘可能已满,文件可能不存在,可能存在权限问题等。

因此,Java 的设计使得程序必须以某种方式在语法上处理异常。这可能是一个 catch 块,或者以某种方式重新抛出异常。

C# 没有检查异常。他们决定将此问题留给应用程序开发人员 (interview)。检查异常是有争议的,因为它们会使代码变得冗长,而开发人员有时会用空的 catch 块来处理它们。此外,哪个标准库方法抛出检查异常可以是任意的。例如,为什么File.delete(一个新的 Java 7 API 的做法不同)不抛出 IOException

Hejlsberg 在采访中指出的另一个问题是版本可控制性。向throw 子句添加已检查异常会强制修改和重新编译使用该方法的所有代码。

【讨论】:

  • Adding a checked exception to a throw clause forces all code using that method to be modified and recompiled - 所以你有未经检查的异常。好吧,除非您认为 Will fail under some circumstances 是您想要描述您的 API 的方式。每个异常都是方法的公共接口的一部分,稍后添加异常就像是在说“哦,从现在开始,该 int 参数将具有完全不同的语义 - 但别担心,它仍然是二进制兼容的!”
  • @Voo,这在采访的this part 中有专门讨论。 Hejlsberg 认为,并不是每个异常实际上都需要由直接调用代码来处理。他说,一些最好由主消息处理程序处理,即使该主处理程序不是在编写新异常的具体知识时。
  • Imo 他使用了一个糟糕的库示例。如果我编写了一个我希望稍后更改的库,我将不得不让它的方法抛出一个足够抽象的异常(例如,一些抛出 SqlException 的通用数据处理程序类显然违反了这个原则)。然后,如果我愿意,我可以稍后添加其他子类,这提供了类似的可能性,但也有类似的缺点。所以是的,我同意 Java 的已检查异常处理存在问题(尽管使用 7 wrt 到样板代码变得更好),[续]
  • 但我认为只有未经检查的异常会误导程序员忽略错误情况并对其 API 进行更改,从而破坏与早期版本的兼容性。我已经看到很多 C# 代码执行此操作,并且充其量只能糟糕地记录抛出的异常,我只是认为这不是更好的方法。另一方面,在过去的几年里,我看到几乎没有人在 Java 中使用 throw Exception - 我认为这有相当大的耻辱感。但是,是的,我仍然希望找到一些解决方案,使我们能够减少检查异常所需的样板,而不会出现未检查异常的缺点。
  • @Voo:我想我希望看到的是一种以声明方式指定从代码调用方法或块中抛出的特定异常应该被包装的方法作为其他东西(RunTimeException,或指定的替代方案)。如果代码将无法做任何有用的事情,例如无法找到解码文档所需的文件,强制该代码捕获异常将无济于事。将检查的异常冒泡为相同类型可能没有帮助,因为调用者可能认为FileNotFoundException 表示未找到文档
【解决方案2】:

在 Java 中,已检查异常(正如 Matthew Flaschen 正确指出的那样)是编译器要求您处理的异常。这些是在函数定义上声明的异常(例如,function bob() throws ImNotBobException { ... } 表示调用该函数可能会引发该异常 - 例如,NumberFormatException 解析整数时,或IOException 写入文件时。

但是,某些异常可能会从未知或意外的地方抛出,这些异常在每个级别上都无法处理,因此编译器不需要您处理这些异常。这些是未经检查的异常。它们可以从没有声明抛出它们的各个地方抛出(通常是在对象尚未初始化时尝试调用该对象的方法,即为空 - 这将导致NullPointerException。)

希望这会有所帮助。

【讨论】:

  • 检查的异常是一个错误。任何其他解释都是错误的。
【解决方案3】:

检查的异常是要求任何“消费”类必须编写显式检查(并希望能处理)异常的代码。

例如,如果 Apple 类有一个包含 WormFound 已检查异常的 Eat() 方法,那么任何调用该方法的代码都需要显式地捕获该异常。

附带说明,它是 Java 的特性,而不是 C# 的特性。

(在创建 C# 时,检查异常的优点在 C# 团队的眼中并不那么明显,因此没有包括在内。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多