一、java异常体系
Thorwable类是所有异常类和错误类的父类,两个直接子类为Error和Exception,分别表示错误和异常。
其中异常类Exception又分为运行时异常(也叫非受检异常)和非运行时异常(也叫受检异常),这两种异常有很大的区别
顾名思义,受检异常也就是编译阶段就检查到的异常,即写代码时还未运行就红线报错的异常。而非受检异常也就是运行时异常是在运行后发现的代码逻辑性错误。
错误和异常不同:
我们看一个错误的例子:
public class Test {
public static void main(String[] args) {
System.out.println("运行");
//调用run方法
run();
}
//定义的run方法
public static void run(){
//递归调用run方法
run();
}
}
我们通过run方法递归,但是没有写递归的终止方法,就会产生错误,这种错误无法自定义抛出,会造成栈溢出,java虚拟机会将线程终止,错误如下图所示:
而异常就是我们经常碰到的红线报错,如语法异常造成的(受检异常):
以及逻辑造成的错误,如数组越界(非受检异常):
1.Error与Exception
error是程序无法处理的错误,它是由jvm产生和抛出的,比如OutOfMemoryError、ThreadDeath等。这些异常发生时,java虚拟机一般会选择线程终止。
Exception是程序本身可以处理的异常,这种异常分为两大类:运行时异常和非运行时异常。程序中应尽可能去处理这些异常。
2.运行时异常和非运行时异常
运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexoutOfBoundsException等,这些异常是非受检异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生
非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
一般受检异常时,我们通常会使用try-catch语句或throws抛出。
try--catch语句:如果代码运行出现了异常,我们把错误的语句放在try代码块里,执行catch代码块里的语句,这样处理不会终止进程,还会执行下面的语句。
如下数组越界的例子:
public class Test {
public static void main(String[] args) {
System.out.println("运行");
int[] a = new int[5];
try {
for (int i = 0; i <10; i++) {
a[i] = i;
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("----------------");
}
}
可以看到执行结果还会在catch语句执行结束后继续向下执行 :
try-catch-finally语句:
1、try、catch、finally三个语句块均不能单独使用,三者可以组成try-catch-finally、try-catch和try-finally三种结构,catch语句可以有多个,finally语句只能有一个。
2.try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问
3.多个catch块的时候最多只会匹配其中一个异常类且只会执行该catch块代码,而不会再执行其他的catch块,且匹配catch语句的顺序从上到下,也可能所有catch都没执行。
4、先catch子类异常,在catch父类异常。
public class Test {
public static void main(String[] args) {
System.out.println("运行");
int[] a = new int[5];
try {
//语句一
for (int i = 0; i <10; i++) {
a[i] = i;
}
//语句二
Class c=Class.forName("不存在的包");
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}catch (Exception e){
System.out.println("捕获的第二个异常");
}
System.out.println("----------------");
}
}
从上面的例子可以看到第二个异常并没有执行。也就是说try里面捕获到一个异常之后就不会再解决try里面的下一个异常。
finally语句是不管有没有出现异常都会执行的一个代码块。
finally常用在:垃圾回收或者是关闭资源
throws关键字:用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用就抛给谁。
用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
例:
public class Test {
public static void main(String[] args) throws Exception {
Math m = new Math() ; // 实例化Math类对象
System.out.println("除法操作:" + m.div(10,2)) ;
}
}
class Math{
public int div(int i,int j) throws Exception{ // 定义除法操作,如果有异常,则交给被调用处处理
int temp = i / j ; // 计算,但是此处有可能出现异常
return temp ;
}
};
一般throws抛出发现异常后会终止线程,不会再继续执行后面的代码。
throw:是用来抛出一个具体的异常类型
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
throw是抛出异常,执行throw是一定抛出了某种异常。
public static void main(String[] args) {
try{
throw new Exception("自己抛着玩的。") ; // 抛出异常的实例化对象
}catch(Exception e){
System.out.println(e) ;
}
System.out.println("11111");
}
执行结果:



