异常
一、异常简介
- 编译错误:基本语法错误,编译器进行语法检查,如果没有通过,程序违背了计算机编程语言的语法
- 运行错误:程序可以执行,在执行过程中发生异常,导致程序提前退出,没有得到预计的执行效果
- 逻辑错误:程序可以执行,结果不对
异常体系,保证程序的健壮性
二、java异常体系结构
Error错误:值JVM相关的不可修复的错误,如:内存溢出,JVM错误等,常见的Error
- Stack OverflowError 栈异常,使用递归没有出口的时候
- OutOfMenoryError 内存不够
RuntimeException:运行时异常:程序运行时抛出,可以通过反复测试尽量避免,不应该靠异常处理机制来解决。
运行时异常 | 说明 |
---|---|
ArithmeticException | 算术异常,如除零操作 |
ArrayIndexOutOfBoundsException | 数组下标越界异常 |
NullPointerException | 访问null对象引用 |
RuntimeException | 运行时异常父类 |
NumberFormatException | 数字格式异常 |
java.lang.ClassCastException | 类型转换异常 |
CheckedException:检查型异常:编译器对代码进行检查,如果没有处理异常,不允许程序通过。
检查型异常 | 说明 |
---|---|
InterruptedException | 线程中断异常 |
FileNotFoundException | 文件找不到异常 |
IOException | 输入输出流异常 |
ClassNotFoundException | 类找不到异常 |
-
没有异常机制存在的问题:
使用方法的返回值来表示异常,无法穷尽所有情况来表示
异常代码和正常流程混在一起了。代码更加臃肿,增加了程序的复杂性,可读性也变低了
随着系统规模扩大,维护性变低了
三、异常处理
3.1 不处理
运行时异常
3.2 捕获
try{
//可能会出现异常,需要接受监视的代码
}catch(异常类型 e){
//当异常发生后,处理预案
}
try{
//可能会出现问题,需要接受监视的代码
}catch(具体的异常类 e){
}finally{
//释放资源
}
/**
如果try 和catch块中,有return语句,finally在return代码之前执行
如果在try 和catch 块中有System.exit(0)退出虚拟机操作,则finally代码块中的语句不再执行
*/
在一个try块中,可能会产生多个异常,在后面可以接多个catch,去捕捉不同的异常。如果try块中,出现异常,直接进入对应的catch块中,try块中出现异常后的代码不会继续执行。
try{
}catch(异常类型1 e){
}catch(异常类型2 e){
}
public class Test1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入两个数字");
int x = scanner.nextInt();
int y = scanner.nextInt();
int[] m = new int[10];
try {
int z = x / y;//y==0
System.out.println(z);
m[10] = 100;//数组下标越界
System.out.println(m[10]);
} catch (ArithmeticException e) {
System.out.println("除数不能为零");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界");
} catch (Exception e) {//必须在最后出现
System.out.println("出现错误");
}
System.out.println("");
}
}
从JDK7版本之后,可以在一个catch块中,捕捉多个异常
Scanner scanner = new Scanner(System.in);
System.out.println("请输入两个数字");
int x = scanner.nextInt();
int y = scanner.nextInt();
int[] m = new int[10];
try {
int z = x / y;//y==0
System.out.println(z);
m[10] = 100;//数组下标越界
System.out.println(m[10]);
}catch (ArithmeticException | ArrayIndexOutOfBoundsException e){//>=JDK7版本
//获取错误消息
System.out.println("出现错误:"+e.getMessage());
}
异常消息的处理
- e.getMessage():获取异常信息
- e.toString():获取异常类和信息
- e.printStackTrace():打印异常堆栈轨迹
如果try和catch操作出现嵌套情况,内部的catch如果不能处理内部try代码块的异常,则由外部的catch块进行捕捉
- 使用finally完成资源释放。例如:关闭打开的连接,删除临时文件,关闭打开文件
- finally不管是否出现异常,都会被执行到。如果try和catch块中,有return语句,finally在return代码之前执行
- 如果try或catch代码块中,执行了System.exit(0)退出虚拟机操作,finally代码块中的语句不再执 try、catch、finally不能单独使用
- try和catch使用
- try、catch和finally使用
- try和finally使用
3.3 抛出
throws、throw关键字
throws用法:
把问题标识出来,报告给调用者,由调用者处理
用在方法上
完成异常抛出,如果一个方法中有可能产生异常,当前方法不做处理,在方法异常列表处 抛出,使用throws关键字。可以接多个异常,中间使用逗号分割。
谁来调用这个方法,谁处理异常
public static Date getDateByString(String str) throws ParseException {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date parse = format.parse(str);
return parse;
}
throw用法:
使用throw抛出指定类型的异常处理。
在方法内部使用
语法格式 throw Throwable类或其子类对象 throw在方法体内的语句,如果抛出的是运行时异常,可以不需要做任何处理。如果抛出的是检查型异 常,不能单独使用,必须要配合try catch 或者throws使用
如果方法中使用throw抛出了异常,认为方法执行完成,后面不能再有语句,除非异常被 使用try、 catch处理了。
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("除数不能为0");
}
return a / b;
}
3.4 自定义异常
继承Throwable 及其子类去编写
public class AgeException extends Exception{
public AgeException() {
super("年龄不符合条件");
}
public AgeException(String message) {
super(message);
}
}
1. 什么时候使用throw, throws ,try…catch
-
- throws:当前方法不需要去处理,只需要提供异常信息,给调用者处理即可
- throw:方法会出现异常时,需要提醒调用者
- try…catch:具体需要处理的时候
2. Exception 和 RuntimeException 的区别
- Exception 是受检查异常,必须处理或者throws 出去
- RuntimeException 运行时异常,运行的时候才去检查
3. 异常对象常用方法:
- getMessage() 获取具体的异常原因
- printStackTrace()//打印具体的错误