【发布时间】:2012-03-11 10:00:06
【问题描述】:
我是一名 C# 开发人员,偶尔使用 Java 编写代码。有人可以简单地解释一下 Java 中的检查异常是什么,为什么需要它?在 C# 中没有遇到过这个术语。
【问题讨论】:
-
Java 中的已检查异常违反了打开/关闭原则。您必须在您和 catch 之间的每个方法的签名中声明该异常。
我是一名 C# 开发人员,偶尔使用 Java 编写代码。有人可以简单地解释一下 Java 中的检查异常是什么,为什么需要它?在 C# 中没有遇到过这个术语。
【问题讨论】:
已检查异常是编译器要求您以某种方式处理的异常。
在 Java 中,已检查的异常是 Throwables,它们不是 RuntimeException、Error 或其子类之一。
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 参数将具有完全不同的语义 - 但别担心,它仍然是二进制兼容的!”
throw Exception - 我认为这有相当大的耻辱感。但是,是的,我仍然希望找到一些解决方案,使我们能够减少检查异常所需的样板,而不会出现未检查异常的缺点。
RunTimeException,或指定的替代方案)。如果代码将无法做任何有用的事情,例如无法找到解码文档所需的文件,强制该代码捕获异常将无济于事。将检查的异常冒泡为相同类型可能没有帮助,因为调用者可能认为FileNotFoundException 表示未找到文档。
在 Java 中,已检查异常(正如 Matthew Flaschen 正确指出的那样)是编译器要求您处理的异常。这些是在函数定义上声明的异常(例如,function bob() throws ImNotBobException { ... } 表示调用该函数可能会引发该异常 - 例如,NumberFormatException 解析整数时,或IOException 写入文件时。
但是,某些异常可能会从未知或意外的地方抛出,这些异常在每个级别上都无法处理,因此编译器不需要您处理这些异常。这些是未经检查的异常。它们可以从没有声明抛出它们的各个地方抛出(通常是在对象尚未初始化时尝试调用该对象的方法,即为空 - 这将导致NullPointerException。)
希望这会有所帮助。
【讨论】:
检查的异常是要求任何“消费”类必须编写显式检查(并希望能处理)异常的代码。
例如,如果 Apple 类有一个包含 WormFound 已检查异常的 Eat() 方法,那么任何调用该方法的代码都需要显式地捕获该异常。
附带说明,它是 Java 的特性,而不是 C# 的特性。
(在创建 C# 时,检查异常的优点在 C# 团队的眼中并不那么明显,因此没有包括在内。)
【讨论】: