运行时/已检查/未检查/错误/exception之间的差异
什么是运行时exception以及什么是选中/未选中的exception以及错误/exception之间的区别。为什么这么多类型? 相反,Java可能只是遵循一个简单的设计(只是尝试/捕获所有类型)来处理程序中的exception情况?
除了所有例外之外,Throwable是最重要的。 在Throwable下面你有错误和exception。 在Exception下面你有RuntimeException。
Java有两种类型的例外 – 已检查和未选中。 检查的exception由编译器强制执行(您必须在throws子句中声明它们并最终捕获它们)。 对throws子句中的捕获或声明不强制执行未经检查的exception。
(有争议的部分答案)
存在Throwable,因此所有exception类型都有父级。 你永远不应该声明你扔掉了Throwable并且永远不会抓住它(除非你真的真的知道你在做什么)。
存在错误表示运行时环境存在问题,程序可能无法从中恢复,例如格式错误的类文件或内存不足的VM。 除非你真的知道自己在做什么,否则不应该发现错误。
exception作为所有非程序员错误的根存在(请参阅RuntimeException以获取此exception),例如由于磁盘已满而无法创建文件。 你不应该抛出,抛出或捕获exception。 如果您必须捕获exception,请确保您知道自己在做什么。
存在RuntimeException以指示所有程序员错误,例如超过数组末尾或调用null对象上的方法。 这些是你应该修复的东西,这样它们就不会抛出exception – 这表明你,程序员,搞砸了代码。 除非你知道自己在做什么,否则你不应该抓住这些。
由于我是一名新的Java开发人员,因此在区分和处理不同类型的exception时也遇到了一些困难。 这就是为什么我在这个主题上做了一个简短的说明,每当我感到困惑时,我都要经历它。 这里是Throwable
类层次结构的图像:
[图片由JavaTpoint提供 ]。
这里要记住三个关键类: Throwable
, Exception
和Error
。 在这些类中, Exception
可以分为两种类型:“Checked Exception”和“Unchecked Exception”。
检查exception:
- 这些是扩展
Throwable
的类,除了RuntimeException
和Error
。 - 它们也称为编译时exception,因为它们在编译时被检查,这意味着编译器强制我们使用
try/catch
处理它们,或者在函数签名中指示它throws
它们并强制我们在调用者中处理它们。 - 它们是程序可恢复的问题,这些问题是由代码控制之外的意外情况引起的(例如数据库关闭,文件I / O错误,错误输入等)。
- 示例:
IOException
,SQLException
等。
未经检查的例外情况:
- 扩展
RuntimeException
的类称为未经检查的exception。 - 未经检查的exception不会在编译时检查,而是在运行时检查,因此名称。
- 它们也是可编程恢复的问题,但与检查exception不同,它们是由代码流或配置中的错误引起的。
- 示例:
ArithmeticException
,NullPointerException
,ArrayIndexOutOfBoundsException
等。 - 由于它们是编程错误,因此可以通过良好/明智的编码来避免它们。 例如,“除以零”会产生
ArithmeticException
,可以通过对除数进行简单检查来避免。 类似地,我们可以通过简单地检查引用来避免NullPointerException
:if (object != null)
或甚至使用更好的技术 。
错误:
-
Error
是指try/catch
未处理的无法恢复的情况。 - 示例:
OutOfMemoryError
,VirtualMachineError
,AssertionError
等。
为什么这么多类型?
除了Stephen C的回答我想说:exception处理在Java中是一个相对昂贵的操作。 我们不应该将所有exception情况放在try/catch
块中。 过度使用try/catch
可能会妨碍程序性能。
最后,应尽可能以编程方式处理Exception
。 另一方面,我们无法处理Error
,因此这可能是为什么有许多类型的exception的一些逻辑原因。
TofuBeer的答案清楚地解释了exception类的含义。
为什么这么多类型? 相反,Java可能只是遵循一个简单的设计(只是尝试/捕获所有类型)来处理程序中的exception情况?
为什么? 因为他们是必要的! 如果没有这4个类,按广义类别处理exception将是不切实际的。
- 如果没有
Error
类,你会如何捕获“所有致命的JVM错误”? - 如果没有
Exception
类,您将如何捕获“不是JVM致命错误的所有exception”? - 如果没有
RuntimeException
类,您将如何捕获“所有未经检查的exception”?
运行时exception为您提供了避免捕获,声明exception的灵活性。
- 错误(由VM引发,不应该被捕获或处理)
- VM错误
- 断言错误
- 链接错误……等等
- 运行时/取消选中exception(编程错误,不应该被捕获或处理)
- 空指针exception
- ArrayIndexOutOfBoundException
- IllegalArgumentException ……等等
- 检查例外(任何其他情况,预计应用程序将被捕获或处理)
- IOExceptionexception
- FileNotFoundExceptionexception
- SQLException …等等
已检查和未检查的exception之间的区别:
我们在已检查和未检查的exception之间存在许多差异,但所有差异都源于一次基本考虑,即exception是否可由编译器解决。
要记住的要点是:
[1]已检查exception表示编译器已检查exception 。 这意味着编译器要求try-catch块或throws关键字处理此类exception。
[2]未经检查的exception是编译器不提供任何授权的exception,因为开发人员可以通过编码/编程来解析它们,因为控制流是可控的,如ArithmeticException,NullPointerException ArrayIndexOutOfBoundsException,IllegalArgumentException等。
我将其称为“Exception-Identity-Test” ,您可以从java doc中获取任何随机exception,只需问一个问题。 “嘿,例外! 你能以编程方式解决吗?“
如果exception表示YES,那么它是未经检查的exception,因为这可以通过代码更改或解决某些计算错误等来解决。
另一方面,如果Exception表示No,那么这是Checked Exception,因为在检查Exception控制流程离开了我们的代码,就像有人更改数据库密码或有人拔掉网络电缆,连接超时(ConnectException),找不到某些资源( FileNotFoundException,ClassNotFound),SQLException,InvocatonTargetException等。这些不能通过编程解决