Java的Exception和Error类都继承自Throwable类。
在java中只有Throwable类才能被捕获和抛出。
而Exception和Error体现出了Java对于不同情况下的异常处理分类。
Exception是在程序运行中可以预料的意外情况,并且可以被捕获和进行相应处理的异常。
Exception分为RuntimeException(不检查异常)和IOException(可检查异常)。
RuntimeException是所谓的运行时异常,常见的类有 NullPointException 和ArrayIndexOutOfBoundsException,这些异常并不强制要求捕获。
IOException主要是指在操作IO时发生的错误,有EOFException FileNotFoundException等需要强制捕获。
接下来就时Error类了,Error是指在正常情况下程序让JVM处于非正常的 不可恢复的状态。如OOM ClassNotFoundError StackOverFlowError
注意事项:
第一,尽量不要捕获类似Exception这样的通用异常,而是应该捕获特定异常,在这里是Thread.sleep()抛出的InterruptedException。
这是因为在日常的开发和合作中,我们读代码的机会往往超过写代码,软件工程是门协作的艺术,所以我们有义务让自己的代码能够直观地体现出尽量多的信息,而泛泛的Exception之类,恰恰隐藏了我们的目的。另外,我们也要保证程序不会捕获到我们不希望捕获的异常。比如,你可能更希望RuntimeException被扩散出来,而不是被捕获。
进一步讲,除非深思熟虑了,否则不要捕获Throwable或者Error,这样很难保证我们能够正确程序处理OutOfMemoryError。
第二,不要生吞(swallow)异常。这是异常处理中要特别注意的事情,因为很可能会导致非常难以诊断的诡异情况。
生吞异常,往往是基于假设这段代码可能不会发生,或者感觉忽略异常是无所谓的,但是千万不要在产品代码做这种假设!
如果我们不把异常抛出来,或者也没有输出到日志(Logger)之类,程序可能在后续代码以不可控的方式结束。没人能够轻易判断究竟是哪里抛出了异常,以及是什么原因产生了异
常。
我们从性能角度来审视一下Java的异常处理机制,这里有两个可能会相对昂贵的地方:
try-catch代码段会产生额外的性能开销,或者换个角度说,它往往会影响JVM对代码进行优化,所以建议仅捕获有必要的代码段,尽量不要一个大的try包住整段的代码;与此同时,利用异常控制代码流程,也不是一个好主意,远比我们通常意义上的条件语句(if/else、switch)要低效。
Java每实例化一个Exception,都会对当时的栈进行快照,这是一个相对比较重的操作。如果发生的非常频繁,这个开销可就不能被忽略了。