java核心技术总结七--异常、日志、断言和调试
第十一章
1、异常的分类:
???? Throwable分为Error类和Exception类。Exception类分为IOException类和RuntimeException类。
????? Error类层次结构描述了java运行时系统的内部错误和资源耗尽错误。
????? 由程序错误导致的异常属于RunntimeException。派生于RuntimeException类的异常包括情况有:错误的类型转换,数组访问越界,访问空指针。
?????? 不是派生于RuntimeException类的异常包括:试图在文件尾部后面读取数据;试图打开一个错误格式的URL;试图根据给定的字符串查找class对象,而这个字符串表示的类并不存在;
??????? Java语言规范将派生于Error类或者RuntimeException类的所有异常称为未检查异常,所有其他的异常称为已检查异常。
?????? c++中有2个基本的异常类:
????????????? runtime_error-------相当于java中的非RuntimeException类
????????????? logic_error--------? 相当于java中的RuntimeException类
?????
2、声明已检查异常:
?????? 必须使用throws子句声明:
?????? ?? 调用一个抛出已检查异常的方法;
????????? 程序运行过程中发现错误,并且利用throw语句抛出一个已检查异常;
????????? 程序出现错误;
????????? java虚拟机和运行时库出现的内部异常
??? 对于那些可能被别人使用的java方法,应该在方法的首部声明这个方法可能跑出的异常,但是不需要声明java的内部错误,即从Error继承的错误,同样也不应该声明从RuntimeException继承的那些未检查异常。
??? 总之,一个方法必须声明所有可能抛出的已检查异常,而未检查异常要么不可控制,要么就应该避免。
??
?? 如果在子类中覆盖了超类的一个方法,子类方法中声明的已检查异常不能超过超类方法中声明的异常范围。如果超类方法没有抛出任何已检查异常,子类也不能抛出任何已检查异常。
?
?? java中的throws说明符和c++中的throw说明符类似。但是在C++中,throw说明符在运行时执行,而不是在编译时执行。另外在C++中如果没有给出throw说明,函数可能会抛出任何异常。在java中,没有throws说明符的方法将不能抛出任何已检查异常。
3、如何抛出异常
???? EOFException异常描述的是"在输入过程中,遇到一个未预期的EOF后的信号"。
???? 对于一个已经存在的异常类,将其抛出的方式是:找到一个合适的异常类;创建这个类的对象;将对象抛出。
???? 在java中,只能抛出Throwable子类的对象,而在c++中,却可以抛出任何类型的值。
4、创建异常类
????? java程序员自己创建的异常类都是继承于Exception的。
5、捕获异常
?????? 如果某个异常发生的时候没有在任何地方进行捕获。那么程序就会终止执行。
??????? 要想捕获一个异常,必须设置try/catch语句块
??????? 通常,应该捕获那些知道如何处理的异常,而将那些不知道怎样处理的异常传递出去。如果想将异常传递出去,就必须在方法的首部添加一个throws说明符。
??????? 如果编写一个覆盖超类的方法,而这个方法又没有抛出异常,那么这个方法就必须捕获方法代码中出现的每一个已检查异常。不允许在子类的throws说明符中出现超过超类方法所列出的异常类范围。
6、再次抛出异常与异常链
????? 在catch子句中可以抛出一个异常,这样做的目的是改变异常的类型
?????? 异常的包装技术: Throwable e = se.getCause();?? 这样可以让用户抛出子系统的高级异常,而不会丢失原始异常的细节。
7、finally子句
????? 不管是否有异常被捕获,finally子句中的代码都被执行。
?????? 将需要关闭资源的子句放在finally子句中是一个很好的选择。
?????? 强烈建议独立使用try/catch和try/finally语句块,这样可以提高代码的清晰度
8、堆栈跟踪元素
?????? 堆栈跟踪是一个方法调用过程的列表,它包含了程序执行过程中方法调用的特定位置。
?????? 可以调用getStackTrace方法获得一个StackTraceElement对象的数组。StackTraceElement类含有能够获得文件名和当前执行的代码行号的方法,同时,还含有能够获得类名和方法名的方法。
9、使用异常机制的建议:
????? 异常处理不能代替简单的测试。使用异常的基本规则是:只在异常情况下使用异常机制;
????? 不要过分的细化异常;
????? 利用异常层次结构,不要只抛出RuntimeException异常,应该寻找更加适当的子类或创建自己的异常类;
????? 不要压制异常;
????? 在检测错误时,"苛刻"要比放任好。例如,当栈空时,Stack.pop是返回一个null,还是抛出一个异常?我们认为,在出错的地方抛出一个EmptyStackException异常要比在后面抛出一个NullPointerException异常更好。
?????? 不要羞于传递异常。有的时候让高层次的方法通告用户发生了错误,或者放弃不成功的命令更加适宜。
?????
????