异常处理,是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况(即超出程序正常执行流程的某些特殊条件)。
这是一个相当重要且必须的功能,有了异常处理,程序员可以很清楚的知道我们的代码是否成功运行,或者如果运行失败运行遇到了什么样的问题,等等。
什么是异常?“异常”指的是程序运行时出现的非正常情况。
异常是方法代码运行时出现的非正常状态,这种非正常状态使程序无法或不能再正常继续往下运行,一些常见的异常包括:数组下标越界、除数为零、内存溢出、文件找不到、方法参数无效、设备缺失等。
导致这种非正常情况的原因有很多,可能是我们程序员写代码时的纰漏,也可能是用户的操作与预期不符,等等。
举例:
比如我们定义了一个int变量,但是我们的输入却是一个字符串"abc"
String s = "abc"; int n = Integer.parseInt(s);//error
又或者我们做除法,但是除数却是0
int a = 1; int b = 0; int n = a / b;//error
以上种种,都是程序运行可能发生的“异常”。因此,一个足够“健壮”的程序,理应在遇到错误或者发现异常时及时结束,并返回相应的错误报告,以便修改。
总结起来,主要有三种:
- 可以被检查的异常(编译时异常):这类异常常由外界因素导致,而如果程序不处理可能会带来意料之外的结果,因此,程序员必须通过异常处理机制来处理这些异常
- 运行时异常:这是一种可以被程序员发现的异常,但是他们往往可以正常编译,Java.lang.RuntimeException类及它的子类都是运行时异常,对于这一类异常程序员必须通过修正自己的代码而非通过异常处理器处理
- 错误(注意他不是异常):这里的错误主要指的是脱离了程序员控制的问题,比如堆栈溢出,而编译器也无法检查到这类异常
所有的异常类都是Exception类的子类
Java程序一般不会捕获错误,Error用来指示运行时环境发生的错误,并且一般是严重错误
Java异常处理的工作机制Java对异常的处理是面向对象的。即异常是一种对象,一个Java的Exception是一个描述异常情况的对象。
Java提供处理异常的是经典的抓抛模型。
抓抛模型指的是:
-
.抛出异常
在程序运行时当语义规则被违反时,将会抛出(throw)异常,即产生一个异常事件,生成一个异常对象
异常类对象的生成:
一般由JVM自动生成:
程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序 try-catch-finally
就会在后台自动创建一个对应异常类的实例对象并抛出,这就是自动抛出或由开发人员手动创建:
如:Exception exception = new FileNotFoundException();
创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样 就相当于 new 了一个异常对象;抛出对象时:
throw exception 手动抛出程序异常
使用情况:
throw new ClassCastException(); 匿名对象形式抛出程序异常如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常
static int method(int x, int y) throws Exception { if (x < y) throw new Exception("x抛出异常实际上只是抛出了异常,并没有进行真正的异常处理
-
捕获异常
异常抛出后,异常对象提交给运行系统,系统就会从产生异常的代码处开始,沿着方法调用栈进行查找,直到找到包含相应处理的方法代码,并把异常对象交给该方法进行处理,这个过程成为捕获(catch)异常。
捕获异常采用try-catch-finally代码块,格式如下:
try { //保护代码块 }catch(FileNotFoundException e){ //Catch块 }catch(IOException e){ //可能需要多重捕获 }catch(NullPointerException e){ //可以有更多的catch块 }finally{ //代码 }try:
try/catch 代码块放在异常可能发生的地方。
try/catch代码块中的代码称为保护代码
catch:
捕获异常之后进行类型匹配,如果不匹配当前的catch块,则继续,直到所有的catch块都被通过或者匹配到为止
finally:
无论是否发生异常,finally 代码块中的代码总会被执行。
在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
finally代码出现在最后
使用情况:预先确定可能会发生异常的代码,提前做好异常捕获处理。
一些注意事项:
- try、catch、finally中声明的变量都是局部变量,意味着在try中声明的变量在catch中可能不存在
- try-catch-finally代码可以嵌套
- catch中的类如果不存在父类子类关系则顺序无所谓,但是如果存在则子类必须在父类上面
String getMessage( ):捕获异常信息。
void printStackTrace(); 方法内部输出异常堆栈信息 一般在catch 中调用
自定义异常类语法格式:
class 类名 extends 父类异常类名 {
};
自定义除法除0错误示例:
class DivideByZeroException extends Exception {
public DivideByZeroException(String msg) {
super(msg);
}
}
//之后,我们可以使用自定义异常,如下所示。
public class Test {
public static void main(java.lang.String[] arg) {
int a = 10;
int b = 0;
try {
divide(a, b);
} catch (DivideByZeroException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
private static int divide(int firstNum,int secondNum) throws DivideByZeroException {
if (secondNum == 0) {
throw new DivideByZeroException("除0错误");
}
else {
return firstNum / secondNum;
}
}
}



