大成若缺,其用不弊。
大盈若冲,其用不穷。
——老子《道德经》
不管人类的思维有多么缜密,也存在“智者千虑必有一失”的缺憾。无论计算机技术怎么发展,也不可能穷尽所有的场景——这个世界是不完美的,是有缺憾的,完美的世界只存在于理想中。
异常封装有三方面的优点:
1、提高系统的友好性,对不同阅读者抛出不同异常提示
2、提高系统的可维护性,对异常进行分类处理
3、解决Java异常机制自身的缺陷,一次抛出多个异常
我们在进行系统开发时不要“吞噬”异常,也不要“赤裸裸”地抛出异常,封装后再抛出,或者通过异常链传递,可以达到系统更健壮、友好的目的。
受检异常时正常逻辑的一种补偿处理手段,但是也有不足之处:
1、受检异常使接口声明脆弱
2、受检异常使代码的可读性降低
3、受检异常增加了开发工作量
受检异常威胁到系统的安全性、稳定性、可靠性、正确性时,不能转换为非受检异常。
finally代码块中出现return返回会出现两个问题:
1、覆盖了try代码块中的return返回值
2、屏蔽异常
不要在finally代码块中出现return语句。
Java的异常机制有三种:
1、Error类及其子类表示的是错误,它是不需要程序员处理也不能处理的异常。
2、RuntimeException类及其子类表示的是非受检异常,是系统可能会抛出的异常,程序员可以去处理,也可以不处理。
3、Exception类及其子类(不包括非受检异常)表示的是受检异常,这是程序员必须处理的异常,不处理则程序不能通过编译。
构造函数中抛出异常,会有三点影响:
1、构造函数抛出错误是程序员无法处理的。
2、构造函数不应该抛出非受检异常,如果抛出:加重了上层代码编写者的负担、后续代码不会执行。
3、构造函数尽可能不要抛出受检异常,不然:导致子类代码膨胀、违背了里氏替换原则(父类能出现的地方子类就可以出现,而且将父类替换为子类也不会产生任何异常)、子类构造函数扩展受限
在构造函数中不要抛出异常,尽量曲线救国。
JVM在创建一个Throwable类及其子类时会把当前线程的栈信息记录下来,以便在输出异常时准确定位异常原因。
用异常当作主逻辑使用有三个错误:
1、异常判断降低了系统性能。
2、降低了代码的可读性。
3、隐藏了运行期可能产生的错误,catch到异常,但没有做任何处理。
异常是主逻辑的例外逻辑,只为确实异常的事件服务。
性能问题不是拒绝异常的借口。