作者回复: 这个留言必须赞!
作者回复: 坏消息是,即使我们记住了所有的JDK异常类,也仅仅是异常世界的一小部分,不够用的。 好消息是,没有人能记住即便是JDK这么少的异常类,所有我们也不要折磨自己去记住所有的异常。
首先要记住,异常是一个可以扩展的类,需要时可以自己定义。所以,你的应用可以有自己定义的异常类。
弄不清楚使用哪种异常,有两种情况比较典型,一种是不了解调用的类;另一种是不了解自己编写的代码的逻辑。这两条清楚了,异常就清楚了。这两条不清楚,代码也很难清楚。
异常就不正常的状况。不正常的状况是什么,搞清楚了,异常该是什么也就知道了八九分。然后,去找合适的现存异常类,或者定义新的异常类,剩下的一两分工作也就凑齐了。
比如说,我回复这条信息的时候,总是输错字母。要是用异常表示,这个不正常的状况就是“键盘输入信息错误”。 然后,在你使用的类库中,去寻找有没有表示这个不正常状况的异常,找到了就用。找不到,如果你想精确定义,就自己定义一个KeyboadInputException; 如果你不想定义新异常,就扩大概念,从“键盘输入信息错误"扩大到"输入信息错误"。然后IOException就是大家都常用的异常了,然后你就可以使用new IOException("键盘输入信息错误")来表示“键盘输入信息错误”这个不正常状况了。
就这样,了解的代码,了解了不正常的状况到底是什么状况。
作者回复: 改的很赞!
另外,有一个小技巧和你分享一下。如果返回值是空值(null),如果调用代码没有检查空值就调用,会抛除NullPointerException异常。如果返回空数组(int[0]), 就不会出现这个问题了。 这个小技巧可以减少调用代码的错误,这样设计的接口比较皮实耐用。如果返回值是数组或者集合,我们通常使用这一个技巧。
作者回复: deal()能不能不抛出异常?或者不正常的时候抛出异常,正常的业务不抛出异常?
使用线程处理更复杂,还不如捕获异常呢。
作者回复: 找的都对。你想到怎么修改了吗?
作者回复: 哈哈,看来你喜欢干脆的结论。
作者回复: 我们先来看看线程的主方法声明“public void run()”。这个声明没有抛出检查型异常,只能抛出运行时异常。所以,检查型异常一定要在线程的实现中得到处理;否则的话,编译器应该报错的。这个方法可以抛出运行时异常。一个线程,像一个普通的方法一样(run()),抛出运行时异常后,线程就终止了。问题在于,线程通常共享资源,如果线程之间有联系,很多事情就会发生,依赖于线程的具体实现逻辑。比如说,如果一个线程要等待另一个线程的I/O,也许会阻塞。
作者回复: 当前线程是发生异常没处理的线程吗? 还是不同的两个线程? 没太明白问题。
作者回复: 新春快乐!
JDK的习惯是,不论是null还是空的集合、数组,都在文档描述中标记清楚。这样,调用者能确切地知道该怎么检查。
作者回复: 简单的说,就是尽量不要使用断言。断言的设计是为了提高代码质量,可是断言一般有三个状态:断言是否启用;如果启用,断言是否成立。这让编码的逻辑很混乱,阅读的时候我们不一定能够把三个逻辑考虑周全,增加了编码错误的几率,降低了代码质量。
作者回复: 有问题就留言,我们一起把疑惑的地方解决掉。
作者回复: 练手题的问题找的都不错啊!