一、异常
1.什么是异常
异常就是一种对象(Exception)java里的异常对象都是派生于Throwable类的一个实例,若java内置的异常类不能够满足需求,用户可以创建自己的异常类。
- 在程序运行过程中,如果JVM检测出一个不可能执行的操作,就会出现运行时错误
- java里运行时错误(Runtime Error)会作为异常抛出
- 如果异常没有被处理,程序将会非正常终止
2.处理异常要做什么
处理异常一般有以下用途:
- 恢复正常的程序执行
- 进行日志处理
- 以某些方式提醒用户(错误提示、对话框)
3.异常的分类
所有的异常都是由Throwable继承而来,并在下一层立即分解为Error和Exception
Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。如果出现了这样的内部错误,除了通告给用户,并尽力使程序安全地终止之外,再也无能为力。
而在设计Java程序时,需要关注Exception层次结构。这个层级结构大致可以分为两个分支:一个是派生于RuntimeException,另一个分支包含其他异常。
由程序错误导致的异常属于RuntimeException,如:
- 错误的类型转换;
- 数组访问越界;
- 访问null指针,
而程序本身没有问题,但由于像IO错误这类问题导致的异常属于其他异常,如:
- 试图在文件尾部后面读取数据;
- 试图打开一个不存在的文件;
- 试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在;
而Java语言规范将派生于Error类或RuntimeException类的所有异常称为非受查异常,其他异常称为受查异常。编译器将会核查是否所有的受查异常提供了异常处理器。(受查异常是我们要求我们自己捕获并处理的,而非受查异常则可省略)
4.异常处理机制
4.1异常处理机制的关键字
- try:监控有可能产生异常的语句块
- catch:以合理的方式捕获并处理异常
- finally:不管有无异常,一定会执行的语句块(一般用来释放资源等)
- throw:手动引发异常
- throws:指定由方法引发的异常
4.2 声明受查异常 - throws
如果遇到了无法处理的情况(或不应在这里处理),那么Java的方法可以抛出一个异常,而调用这个方法就必须捕获并处理这个异常或继续向上层抛出异常。(用 throws 抛出的应当是受查异常)如:
public FileInputStream(String name) throws FileNoFoundException, EOFException{
}
注意:
- 有 throws 声明异常,但在方法体中,并不一定需要有 throw 抛出相应的异常,这是为异常先占个位置,以后就可以抛出这种异常而不用修改已有的代码。对定义抽象基类和接口时,这点很重要。
- 如果子类覆盖了父类的已声明的异常的一个方法,那么子类的方法中可以抛出更特定的异常,或者根本不抛异常
- 如果子类覆盖了父类没有声明异常的一个方法,那么子类的方法中最好也不要抛出受查异常
4.3 抛出异常 - throw
若在方法体中将会发生异常,可以自己手动抛出,如:
throw new FileNoFoundException;
也可以抛出自己定义的异常,如:
public void setAge(int age) throws Exception{
if(age < 30) {
this.age = age;
}else {
throw new Exception("年龄过大");
}
}
4.4 捕获异常 - try catch finally 语句
异常发生的时候,必须要有一个地方进行捕获,否则将会导致程序终止执行。而捕获异常就需要用到 try-catch-finally 语句块。
其中finally语句块不是必要的,finally语句块里一般用于释放资源。
如:
try {
System.out.println("可能的异常发生前");
stu.setAge(50); // 传入大于30即会发生异常
System.out.println("可能的异常发生后");
} catch (Exception e) {
e.printStackTrace();
System.out.println("\n 这里只有捕获了异常才会执行");
}
finally {
System.out.println("这里是无论是否发送异常都会执行");
}
System.out.println("若未捕获到正catch里的异常,这里不会被执行");
4.5 捕获多个异常
一个try语句块可以捕获多个异常类型,并对不同类型的异常做出不同的处理。可以按照夏磊方式为每个异常类型使用一个单独的catch子句
try{
//可能发生异常的地方
}
catch(FileNotFoundException e) {
//文件未找到的异常处理
}
catch(IOException e) {
// IO异常的处理
}
若不同异常的处理都是一致的,可合并catch子句
try{
}
catch(FileNoFoundException | UnknownHostException e){
}
4.6 创建异常类
在程序中可能会遇到任何标准异常都没有能够充分描述清楚的问题。在这种情况下,就可以去创建自己的异常类。只需要定义一个派生于Exception的类,或者派生于Exception子类的类。
创建自定义的类,最简单的方式,只需要写两个构造器,一个是默认的构造器,另一个是带有详细描述信息的构造器(超类Throwable 的 toString 方法将会打印出这些详细信息)
class AgeMoreThanThirtyException extends Exception{
public AgeMoreThanThirtyException(){
}
public AgeMoreThanThirtyException(String message){
super(message)
}
}