1.简介
Java中的所有异常均继承与Throwable,其子类包括Error和Eexception,主要包括以上三种:
- Error:是比较严重的异常,一般如果产生该类异常,程序就会彻底崩溃,该异常程序猿不太容易及时解决,如开发环境配置有误、虚拟机错误和线程死锁等;
- 运行时异常:该异常在编译时可以通过,但在运行时暴露,通常该异常可通过程序员的检测,避免发生,例如空指针、数组角标越界和类型转换等;
- 检查异常:该异常通常是程序员不可预见的异常,例如用户的输入错误和打开文件不存在,数据库操作有误等。
2.异常处理
2.1Java内置异常处理
Java的源码中包括一些内置的异常处理,该异常处理在java.lang包中,因此大部分运行时异常可以直接使用,例如:
非检查异常 | 描述 |
---|---|
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
检查异常 | 描述 |
---|---|
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
NoSuchFieldException | 请求的变量不存在 |
2.2 异常处理
2.2.1 捕获
使用try cath关键字捕获异常,将可能发生异常的代码放置在try语句的括号中,将可能产生的异常处理情况放置在catch语句中。
try
{
// 可能发生异常代码
}catch(ExceptionName e1)
{
//针对该异常产生,做出相应的异常处理
}
通常在一段代码块可能会产生多种异常,需要多次捕获异常,例如下面的示例代码,程序执行时可能产生三种异常情况,需要分别处理,但这里需要注意,通常异常的级别自上而下是由小至大的,也就是最下的异常通常是最大的,例如Exception,因为当异常发生时是根据代码的距离逐一匹配处理的。
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 异常处理代码1
}catch(异常类型2 异常的变量名2){
// 异常处理代码2
}catch(异常类型3 异常的变量名3){
// 异常处理代码3
}
2.2.2 抛出异常
如果采用捕获操作时,无法捕获到检查性异常时,需采用throw/throws关键字来声明异常,throws放在方法的尾部,而throw是在代码的内部,是由程序猿主动抛出异常。例如:
public static void test() throws NumberFormatException {
String s = "abc";
System.out.println(Double.parseDouble(s));
}
将String强制转为Double时会抛出NumberFormatException 异常。
public static void test(String s) {
if(s.equals("abc")){
throw NumberFormatException() ;
}
}
判断如果传入的参数s为“abc”时,主动抛出异常。
注意,throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
2.2.3 finally 关键字
finally关键字是用来创建在try代码后执行的代码块,无论异常是否会发生,都会执行,可对异常的处理进行收尾操作,例如IOException时关流处理。
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 异常处理代码1
}catch(异常类型2 异常的变量名2){
// 异常处理代码2
}finally{
//收尾处理代码
}
2.3 自定义异常
在自定义异常时需要注意一下几点:
- 所有的异常必须是Throwable的子类;
- 如果是检查性异常,则直接继承Exception;
- 如果是运行时异常,则继承RuntimeException。
例如:
class MyException extends Exception{
}
和普通的类声明类似,也可以在异常类中添加变量和方法,在需要异常处理时调用该类中的变量和方法进行相应的处理。