JAVA的异常
1. 异常的背景
2. 异常的用法
3. 异常处理流程
1. 异常的背景
①除数为0的异常:
System.out.println(10/0);
②数组越界异常:
int[] arr = {1,2,3};
System.out.println(arr[100]);
③访问null对象:
public int num = 10;
public static void main(String[] args) {
test_abnormal t= null;
System.out.println(t.num);
}
总结:所谓的异常就是运行时出现错误,通知调用者的一种机制。异常的种类有很多,不同种类的异常具有不同的含义,也有着不同的处理方式。
2. 异常的用法
①捕获异常
int a = 0;
try{
System.out.println(10/a);
}catch(ArithmeticException e){
a = 1;
System.out.println(10/a);
//e.printStackTrace();//打印异常
}
若通过e.printStackTrace();//打印异常,并且使用finally代码块
int a = 0;
try{
System.out.println(10/a);
System.out.println("try code");
}catch(ArithmeticException e){
System.out.println("catch code");
e.printStackTrace();//打印异常
}finally{
System.out.println("finally code");
}
}
从中可以看出,一旦try代码块出现异常,那么try代码块中的程序就不会被执行,而是交给catch代码块来执行。catch代码块执行完毕后,继续往下执行。
如果不处理或者catch代码块未捕捉到,就会交给JVM来处理,这时程序会异常终止,不会往下执行。
②catch代码块未捕捉的情况:
try{
System.out.println("before");
int[] arr = {1,2,3};
System.out.println(arr[100]);
System.out.println("after");
}catch(ArithmeticException e){
e.printStackTrace();
}
这里catch语句不能捕获异常,是因为异常的类型不匹配。
③catch代码块可以有多个:
try{
System.out.println("before");
int[] arr = {1,2,3};
System.out.println(arr[100]);
System.out.println("after");
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("这是个数组下标越界的异常");
}catch(NullPointerException e){
System.out.println("这是个空指针异常");
}
如果多个异常的处理方式完全相同,可以写成这样
catch(ArrayIndexOutOfBoundsException |NullPointerException e){
...
}
④向上传递
public static void main(String[] args) {
try{
func();
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();//打印异常
}
System.out.println("after try catch");
}
public static void func(){
int[] arr = {1,2,3};
System.out.println(arr[100]);
}
如果没有合适的方法处理异常,就会沿着调用栈向上传递。本例中,func()没有处理异常,会交给main()函数处理异常,若一直得不到处理,就会交给JVM来处理,程序就会异常终止。(这种情况和未使用try catch一样)
⑤关于finally的注意事项
public static void main(String[] args) {
System.out.println(func());
}
public static int func(){
try {
return 10;
}finally{
return 20;
}
}
一般不建议在finally代码块中写return,会出现警告。
finally的返回时机是在方法返回之前,或者catch中如果有return,会在这个return之前执行finally,但如果finally中也存在return,就会执行finally中的return,从而不会执行try中原来的return。
总结:
1.try代码块中放的是可能出现异常的代码
2.catch代码块中是处理异常的代码
3.finally代码块用于处理善后工作,会在最后执行
4.catch代码块和finally代码块都可以根据情况加或者不加
5.无论是否发生异常,finally代码块一定会被执行到
3. 异常处理流程
1.程序先执行try代码块
2.如果try代码块中出现异常,就会结束执行try代码块,看和catch代码块中的异常类型是否匹配
3.如果匹配,就会执行catch代码块
4.如果不匹配,就会将异常向上传递到上层调用者
5.无论是否找到匹配的类型,finally代码块一定会被执行到
6.如果上层调用者没有处理异常,就继续向上传递
7.一直到main()方法也没有处理异常,就交给JVM来处理,程序就会异常终止
处理异常:
//throws声明异常,一般抛给上层调用者
public static int divide(int x,int y) throws ArithmeticException{
if(y == 0){
//抛出异常
throw new ArithmeticException("抛出0异常");
}
return x/y;
}