异常机制是指当程序出现错误时,提供了给程序退出的安全通道的机制。
Java中,所有异常都有一个共同的祖先 Throwable,Throwable有两个重要的子类:Exception(异常)和 Error(错误),异常和错误的区别在于:异常是能够被程序本身处理的,错误无法处理。
是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,多数与代码运行时 JVM 出现的问题有关。
是程序本身可以处理的异常,异常一般分两大类:运行时异常和非运行时异常(受检异常)。
运行时异常
都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、ArrayIndexOutOfBoundsException(下标越界异常)等, 这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序员应该从逻辑角度尽可能避免这类异常的发生。运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
受检异常(checked exceptions)
从语法角度上来说,非运行异常都是必须进行处理的异常, 如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。 受查异常是编译器必须处理的,要么使用try-catch语句捕获,要么使用throws子句抛出异常,否则编译会不通过。
Java程序中,异常处理机制为:抛出异常和捕获异常。
如果当前方法不知道如何处理该异常时,可以使用Throws或Throw语句将异常抛出给调用者处理或者交给JVM。
throws语句用在方法定义时声明该方法要抛出的异常类型 ,throws语句的语法格式为:
methodname throws Exception1,Exception2,..,ExceptionN { }
方法名后的throws Exception1,Exception2,…,ExceptionN 为声明要抛出的异常列表。当方法抛出异常列表的异常时,方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。
使用throws关键字将异常抛给调用者后,如果调用者不想处理该异常,可以继续向上抛出,但最终要有能够处理该异常的调用者。
throw总是出现在方法体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。
throw new exceptionname;
throw示例:
public class TestException {
public static void main(String[] args) {
int a = 6;
int b = 0;
try {
if (b == 0) {
throw new ArithmeticException();
//"除数为0"等ArithmeticException,是RuntimException的子类。而运行时异常将由运行时系统自动抛出,不需要使用throw语句,这里把throw new ArithmeticException()去掉也是不影响运行结果的。
}
System.out.println("a/b的值是:" + a / b);
} catch (ArithmeticException e) {
System.out.println("程序出现异常,变量b不能为0。");
}
System.out.println("程序正常结束。");
}
}
输出结果:
程序出现异常,变量b不能为0。
程序正常结束。
位置不同
1. throws用在函数上,后面跟的是异常类,可以跟多个;而throw用在函数内,后面跟的是异常对象。
功能不同
1. throws用来声明异常,让调用者只知道该功能可能出现的问题,可以给出预先的处理方式;throw抛出具体的问题对象,执行到throw,功能就已经结束了,跳转到调用者,并将具体的问题对象抛给调用者。也就是说throw语句独立存在时,下面不要定义其他语句,因为执行不到。
2. throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
捕获异常通过try-catch语句或者try-catch-finally语句实现。
try {
// 可能会发生异常的程序代码
} catch (Type1 id1){
// 捕获并处置try抛出的异常类型Type1
} catch (Type2 id2){
//捕获并处置try抛出的异常类型Type2
}
/******************************/
try {
// 可能会发生异常的程序代码
} catch (Type1 id1){
// 捕获并处置try抛出的异常类型Type1
} catch (Type2 id2){
//捕获并处置try抛出的异常类型Type2
}finally {
// 无论是否发生异常,都将执行的语句块
}
Java方法在运行过程中出现异常,则创建异常对象。将异常抛出监控区域(try关键词后面的大括号括起来的代码区域)之外,由Java运行时系统试图寻找匹配的catch子句以捕获异常。若有匹配的catch子句,则运行其异常处理代码,try-catch语句结束,不会再有匹配其他异常的机会。
try、catch、finally语句块的执行顺序:(重要)
1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;
2)当try捕获到异常,catch语句块里没有处理此异常的情况:此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;
3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句。
Java 常见异常种类