异常
异常的分类
异常对象都是派生于Throwable类的一个实例。如果Java内置的异常类不能够满足需求,用户还可以创建自己的异常类。
所有的异常类都是由Throwable继承而来,在下一层分解为两个分支:Error和Excpetion:
Error类描述了Java运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。如果出现这样的内部错误,除了通知用户并尽力使程序安全终止外,再也无能为力了。这种情况很少出现。
Exception异常由分解为两个分支:
(1)派生于RuntimeException异常:由于程序设计错误导致的异常属于RuntimeException。
派生于RuntimeException的异常包括:
- 错误的类型转换;
- 数组访问越界;
- 访问空指针;
(2)曾经能够正确运行,而由于某些情况如IO错误,导致的错误属于其他异常:
不是派生于RuntimeException的异常包括:
- 试图打开一个错误格式的URL;
- 试图在文件尾部后面读取数据;
- 试图根据给定的字符串查找Class对象,而这个字符串表示的类不存在;
如果出现RuntimeException异常就一定是你的问题。例如通过检测数组下标是否越界来避免ArrayIndexOutOfBoundsException异常;通过使用变量之前检测是否为空来杜绝NullPointerException异常。
未检查异常 VS 已检查异常
派生于RuntimeException类或Error类的所有异常成为未检查(unchecked)异常;其他的异常称为已检查(checked)异常。
与C++异常比较
C++有两个基本的异常类,一个是runtime_error,另一个是logic_error。logic_error相当于Java中的RuntimeException,它表示程序中的逻辑错误;runtime_error类是所有由于不可预测的原因所引发的异常的基类,相当于Java中的非RuntimeException异常。
抛出异常
方法应该在首部声明所有可能抛出的异常,这样可以从方法的首部反映出该方法可能会抛出哪类已检查异常:
public FileInpitStream(String name) throws FileNotFoundException, ... , ... , ... ...
一个方法必须声明所有可能抛出的已检查异常。不需要声明Java的内部错误,就是从Error继承的那些异常,任何程序代码都具有抛出这类异常的潜能,而我们对它们却没有任何控制能力。同样,也不应该声明从RuntimeExeption继承的那些未检查异常。
抛出异常方法的继承
如果在子类中覆盖了超类的一个方法,那么,子类方法中声明的已检查异常不能超过超类方法中声明的异常范围。也就是说,子类方法中抛出的异常范围更加小,或者根本不抛出任何异常。如果超类方法没有抛出任何已检查异常,那么,子类也不能抛出任何已检查异常。
捕获异常
断言 assert