异常处理的几种方式:
1:throw
什么是throw?
在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。
在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。
throw格式:
修饰符 返回值类型 方法名(参数列表) [throws 异常的类型] {
if (判断条件) {
throw new 异常对象("异常的原因");
}
}
代码演示:
public class ThrowDemo {
public static void main(String[] args) {
//创建一个数组
int[] arr = {2,4,52,2};
//根据索引找对应的元素
int index = 4;
int element = getElement(arr, index);
System.out.println(element);
System.out.println("over");
}
/*
* 根据 索引找到数组中对应的元素
*/
public static int getElement(int[] arr,int index){
//判断 索引是否越界
if(index<0 || index>arr.length-1){
/*
判断条件如果满足,当执行完throw抛出异常对象后,方法已经无法继续运算。
这时就会结束当前方法的执行,并将异常告知给调用者。这时就需要通过异常来解决。
*/
throw new ArrayIndexOutOfBoundsException("哥们,角标越界了~~~");
}
int element = arr[index];
return element;
}
}
注意事项:
1.throw关键字必须写在方法的内部
2.throw关键字后边new的对象必须是Exception或者Exception的子类对象
3.throw关键字抛出指定的异常对象,我们就必须处理这个异常对象
throw关键字后边创建的是RuntimeException或者是 RuntimeException的子类对象,我们可以不处理,默认交给JVM处理(打印异常对象,中断程序)(推荐)
throw关键字后边创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么throws,要么try...catch
2:throws
-
什么是throws?
-
throws方式处理异常 又被称之为声明异常,将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws进行声明,让调用者去处理。
关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).
-
声明异常的格式:
修饰符 返回值类型 方法名() throws 异常类名 { }
-
代码演示
public class ThrowsDemo {
public static void main(String[] args) throws FileNotFoundException {
read("a.txt");
}
// 如果定义功能时有问题发生需要报告给调用者。可以通过在方法上使用throws关键字进行声明
public static void read(String path) throws FileNotFoundException {
if (!path.equals("a.txt")) {//如果不是 a.txt这个文件
// 我假设 如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常 throw
throw new FileNotFoundException("文件不存在");
}
}
}
throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗号隔开。
public class ThrowsDemo2 {
public static void main(String[] args) throws IOException {
read("a.txt");
}
public static void read(String path)throws FileNotFoundException, IOException {
if (!path.equals("a.txt")) {//如果不是 a.txt这个文件
// 我假设 如果不是 a.txt 认为 该文件不存在 是一个错误 也就是异常 throw
throw new FileNotFoundException("文件不存在");
}
if (!path.equals("b.txt")) {
throw new IOException();
}
}
}
3:throw和throws的区别
4: try catch
try {
//放置程序可能出现问题的代码
} catch (异常类型 异常名称) {
//放置处理之后的代码
}
public class Main {
public static void main(String[] args) {
int i = 10;
try {
System.out.println(i/0);
} catch (ArithmeticException e) {
System.out.println("除数为0异常");
}
}
}
5:try-catch-finally
-
什么是finally?
有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
-
不管有没有出现异常,finally代码块都会执行;
-
不管try和catch的代码块中有return时,finally仍会执行,且如果finally代码块也有return,则此代码肯定会返回finally执行的return值。
try { 可能出现异常的代码; } catch(异常类名 变量名) { 异常的处理代码; } finally{ 释放资源 } 注意:finally不能单独使用。必须配合着try…catch使用
分有return和没有return来讨论try-catch-finally执行顺序的情况:
有return:
-
try{} catch(){} finally{} return; 程序按顺序执行
-
try块中有return
try{return 1;} catch(){} finally{} return 2; 程序执行try块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,最后执行try中return; finally块之后的语句return不再执行,因为程序在try中已经return过了。 结论:得到try中的返回值1。
-
catch块中有return
try{} catch(){return 1;} finally{} return 2; 程序先执行try,如果遇到异常执行catch块, 有异常:执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,最后执行catch块中return。 finally之后的return不再执行。 无异常:执行完try再finally再return。 结论:有异常影响catch,执行catch中的return得到返回值1。
-
try块和finally块中有return
try{return 1;} catch(){} finally{return 2;} 无异常:程序执行try块中return之前(包括return语句中的表达式运算)代码;再执行finally块,因为finally块中有return所以提前退出,而不再执行try中的return; 有异常:不执行try,顺序执行catch-finally 结论:得到finally中的返回值2。
-
catch块和finally块中有return
try{} catch(){return 1;} finally{return 2;} 无异常:执行try后跳过catch执行finally;得到finally的返回值2; 有异常:程序执行catch块中return之前(包括return语句中的表达式运算)代码;再执行finally块,因为finally块中有return所以提前退出。而不再执行catch中的return。 结论:得到finally中的返回值2。
-
try块、catch块和finally块中有return
try{return 1;}
catch(){return 2;}
finally{return 3;}
程序执行try块中return之前(包括return语句中的表达式运算)代码;
无异常:然后再执行finally块,因为finally块中有return所以提前退出。
有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;再执行finally块,因为finally块中有return所以提前退出。
结论:得到finally中的返回值3。
没return:
举个例子:
try {
t();
tt();
} catch (Exception e) {
c();
} finally {
f();
}
m();
-
当try中的t()没有抛出异常
因为没有捕捉到异常,那么执行try而不会执行catch,而finally无论如何都要执行。
其执行顺序为:t() --> tt() --> f() --> m() -
当try中的t()抛出了异常
当 t() 中抛出异常,那么 t() 中从抛出异常的语句之后的代码以及 tt() 都不会执行, 程序会尝试捕捉异常。
捕捉Exception,捕捉成功,执行 c() ;
一旦捕捉到一个异常,不会再尝试捕捉其他异常,直接执行finally里的f();
执行后面的函数 m() 。
其执行顺序为:t() --> c() --> f() --> m()
tch,而finally无论如何都要执行。
其执行顺序为:t() --> tt() --> f() --> m() -
当try中的t()抛出了异常
当 t() 中抛出异常,那么 t() 中从抛出异常的语句之后的代码以及 tt() 都不会执行, 程序会尝试捕捉异常。
捕捉Exception,捕捉成功,执行 c() ;
一旦捕捉到一个异常,不会再尝试捕捉其他异常,直接执行finally里的f();
执行后面的函数 m() 。
其执行顺序为:t() --> c() --> f() --> m()