异常
在Java语言中,将程序执行中发生的非正常情况称为“异常”。
注:开发过程中的语法错误和逻辑错误不是异常
执行过程中所发生的异常事件可分为两类:
- Error: Java虚拟机无法解决的严重问题
如:JVM系统内部错误、资源耗尽等严重情况,一般不编写针对性的代码进行处理 - Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理
如:空指针访问、数组角标越界、试图读取不存在的文件等
Java的异常机制
在java中,异常以类的形式存在,当程序运行过程中发生意外情况,虚拟机就会在底层创建出一个异常对象,将相关的异常信息打印输出。
异常机制优点
- 更好的容错性
- 更强的健壮性
异常处理
1. try-catch-finally
常规步骤:
- 使用try包裹可能出现的异常代码块
- 使用 catch 去捕获这个异常对象,做出相应的处理
- 使用finally执行必须要执行的代码块
public static void main(String[] args) {
String[] arr = new String[]{"aa", "bb", "cc", "dd", "ee"};
try {
for (int i = 0; i < 8; i++) {
System.out.println(arr[i]);
}
// java7以后,支持多异常的处理
} catch (ArrayIndexOutOfBoundsException | ArithmeticException e) {
// 此处的内容应该是异常的处理方式
// 简单的进行语句打印
System.out.println("Handling ArrayIndexOutOfBoundsException, waiting a moment, please.");
} catch (Exception e) {
System.out.println("Handling Exception,waiting a moment, please.");
} finally {
// 通常,用来回收物理资源
System.out.println("The exception has been handled!");
}
}
抓抛方式小结:
- catch 后面括号中的参数,就是异常对象参数,意思就是如果出现的这个异常对象属于括号里的这个异常,那么就进入该catch 块去处理这个异常
- 异常是以类的形式存在,需要为这个异常对象定义一个 catch 块。异常对象会根据catch 后的参数去找属于自己的那一个 catch 块,找到就进入该 catch 块,即异常被捕获,没有的话,程序就会因为异常而终止
- 异常对象一旦被一个 catch 捕获,就不会再进入下一个异常了,因此,先捕获处理小范围的异常,再捕获处理大范围的异常,也就是先小后大
- 异常对象无论进入哪个 catch 块执行,或者是否进入catch块,finally 里的代码一定会被执行,通常,被用于释放资源,比如说数据库连接、网络连接或者常见的 IO 流的操作等
- 对于异常处理,必须有try ,而 catch 和 finally 不是必须都要,至少选择其一
- 当产生一个异常对象,被相对应的 catch 块捕获之后,这个 catch 块后的异常形参 去获得一些异常信息,一般我们常用的一些方法 如下:
getMessage():这个方法会返回异常的详细描述信息
printStackTrace():这个方法会打印出异常的跟踪栈信息
printStackTrace(PrintStream p):这个则会将异常的跟踪栈信息输出到指定的输出 流中去
getgtacktreace():返回异常的跟踪站信息
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
e.printStackTrace();
输出结果
2. 声明抛出异常
如果一个方法可能生成某种异常,但不能确定如何处理这种异常,则此方法应显式地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
俗称“摆烂”,自己不管了,就往上抛,抛出去,谁爱管谁管。
最终如果一直向上抛到JVM,就必须进行处理了,如果无法处理的话,就会打印异常的跟踪栈信息,并中止程序
//声明抛出模型不支持多异常处理,在方法声明处只抛出一个异常类型
// 类中可能出现的异常,或者该异常的父类
public static void main(String[] args) throws ArrayIndexOutOfBoundsException {
String[] arr = new String[]{"aa", "bb", "cc", "dd", "ee"};
for (int i = 0; i < 8; i++) {
System.out.println(arr[i]);
}
}
运行结果
3. 手动抛出异常
Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要,使用人工创建并抛出。
首先要生成异常类对象,然后通过throw语句实现抛出操作(提交给Java运
行环境)。
IOException e = new IOException();
throw e;
可以抛出的异常必须是Throwable或其子类的实例。下面的语句在编译时将
会产生语法错误:
throw new String("want to throw");
4. 自定义异常
- 一般地,用户自定义异常类都是RuntimeException的子类。
- 自定义异常类通常需要编写几个重载的构造器。
一个无参构造器
一个带有字符串参数的有参构造器 - 自定义异常需要提供serialVersionUID
- 自定义的异常通过throw抛出。
- 自定义异常最重要的是异常类的名字,当异常出现时,可以根据
名字判断异常类型。
用户自定义异常类MyException,用于描述数据取值范围错误信息。用户
自己的异常类必须继承现有的异常类
class MyException extends Exception {
static final long serialVersionUID = 13465653435L;
private int idnumber;
public MyException() {
}
public MyException(String message, int id) {
super(message);
this.idnumber = id;
}
public int getId() {
return idnumber;
}
}