Java–异常
1 异常分类
-
在java中,异常对象都是派生于Throwable类的一个实例;如果java内置的异常类不能满足需求,用户可以自己创建自己的异常类
-
Error 层次描述的是java运行时系统的内部错误和资源耗尽错误,如果出现这样的错误,除了通告给用户,还要尽力使程序安全终止
-
Exception
- RuntimeException 程序错误导致的异常
- 错误的类型转换
- 数组访问越界
- 访问null指针
- IOException 程序本身没有问题,IO错误导致的异常
- 试图在文件尾部后面读取数据
- 试图打开一个不存在的文件
- RuntimeException 程序错误导致的异常
-
java将派生于Error类和RuntimeException类的异常成为非受查异常(unchecked),其他的异常程序受查异常(checked)
-
非受查异常unchecked 这种异常是运行时发生,无法预先捕捉处理的。Error也是unchecked exception,也是无法预先处理的
-
受查异常checked 可以检查到的异常,所有checked exception都是需要在代码中处理的。它们的发生是可以预测到的。比如IOException,或者一些自定义的异常。
常见的非检查异常
常见的检查异常
2 异常处理
- Java异常机制用到的几个关键字:try、catch、finally、throw、throws。
- try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
- catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
- finally – 无论发生异常,finally语句块总是会被执行,出现在catch代码块最后。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
- throw – 用于抛出异常。
- throws – 用在方法后,用于声明该方法可能抛出的异常。主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。
//try-catch 捕获异常
try {
code;
more code;
}
catch(ExceptionType e) {
handler for this type;
}
catch(ExceptionType d){
handler for this type;
}finally{
code;
}
// 这个方法有可能抛出一个IOException
public void read(String filename) throws IOException{
InputStream in = new FileInputStream(filename);
...
}
- try-catch-finally 执行顺序
例子1
public static void main(String[] args){
int result = test3();
System.out.println(result);
}
public static int test3(){
//try 语句块中有 return 语句时的整体执行顺序
int i = 1;
try{
i++;
System.out.println("try block, i = "+i);
return i;
}catch(Exception e){
i ++;
System.out.println("catch block i = "+i);
return i;
}finally{
i = 10;
System.out.println("finally block i = "+i);
}
}
输出
try block, i = 2
finally block i = 10
2
- 由于finally块始终会被执行的原因就是 编译器会把finally块中的代码复制两份分别放在try和catch的后面
例子2
public static int test4(){
//finally 语句块中有 return 语句
int i = 1;
try{
i++;
System.out.println("try block, i = "+i);
return i;
}catch(Exception e){
i++;
System.out.println("catch block i = "+i);
return i;
}finally{
i++;
System.out.println("finally block i = "+i);
return i;
}
}
输出
try block, i = 2
finally block i = 3
3
最终会采用 finally 代码块中的 return 语句进行返回,而直接忽略 try 语句块中的 return 指令。
最后,对于异常的使用有一个不成文的约定:尽量在某个集中的位置进行统一处理,不要到处的使用 try-catch,否则会使得代码结构混乱不堪。