异常的处理方式:
异常处理的两种方式 :
- try-catch 式
- throws 式
一、try-catch式:
本人先通过一张图来展示下 try-catch式 的运行顺序:
至于finally 的内容,则是不论try内是否发生了异常,都会运行的语句,哪怕在try-catch 的内部return ,也会在return前运行。
现在,本人来展示下try-catch式的两种格式:
① try…catch…finally格式:
try {
可能出现问题的代码 ;
} catch(异常名 变量名) {
针对问题的处理 ;
} finally {
释放资源;
}
(有时候finally那个代码块我们可以不用写)
那么,本人现在来展示下异常的 try-catch式 中的 try…catch…finally的格式 的处理方式:
本人来解决“内存泄漏”的问题:
package about_io;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
try {
int num;
num = in.nextInt();
System.out.println(num);
} catch (Exception e) {
} finally { //finally : 无论是否发生异常,都会执行。(可用于解决内存泄漏问题)
System.out.println("结束输入");
in.close();
}
}
}
那么,我们再来运行一遍,看一下结果:
② try…catch…格式:
try {
可能出现问题的代码 ;
} catch (异常名1 变量名1){
对异常的处理方式 ;
} catch (异常名2 变量名2){
对异常的处理方式 ;
}....
现在,本人来讲解下 使用 try-catch格式 的 注意事项:
注意事项:
- 能明确的 异常,尽量明确
- 多个异常类,如果是平级关系,在前在后没关系
- 多个异常类,存在继承关系,父类异常要放在后面
为了验证上面的语法条件约束,本人来给出一个错误的例子:
package about_io;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 0;
int[] arr={1,2};
arr=null;
//try里面一般放置,有可能会出现问题的代码
//catch(某种异常) 一旦出现某种异常,catch 就会捕获该异常
//一旦try种出现该种异常,那么相应的cathe就会执行
//捕获异常的注意事项:
//1.能明确的 异常,尽量明确
//2.多个异常类,如果是平级关系,在前在后没关系
//3,多个异常类,存在继承关系,父类异常要放在后面
try {
System.out.println(a / b); //这行代码有可能会出现异常
System.out.println(arr.length);
} catch (Exception e){
System.out.println("未知异常");
} catch (ArithmeticException e){
//一旦遇到这个异常,怎么去处理
System.out.println("除数为0了");
} catch (NullPointerException e){
System.out.println("空指针异常");
}
System.out.println("下面的程序");
}
}
可以看到,当我们在捕获父类异常后再来捕捉子类异常,编译器就会报错
但是在JDK7之后,我们也可以将多异常写成如下格式:
try {
可能出现问题的代码 ;
}catch(异常名1 | 异常名2 | .... 变量名){
对异常的处理方案 ;
}
这样的处理方式,相对于上面的处理方式,有如下优缺点:
好处:
就是简化了代码
弊端:
对多个异常的处理方式是一致的
但是,这种处理方式是有条件的:
新式catch结构 的 条件:
条件:
多个异常之间只能是平级的关系,不能出现子父类的继承关系
为了验证上面的语法条件约束,本人来给出一个错误的例子:
package about_io;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 0;
int[] arr={1,2};
arr=null;
try {
System.out.println(a / b); //这行代码有可能会出现异常
System.out.println(arr.length);
//多个异常之间只能是平级的关系,不能出现子父类的继承关系
} catch (ArithmeticException | NullPointerException | Exception e){
System.out.println("发生了异常");
}
System.out.println("下面的程序");
}
}
最后,本人再来强调一个try-catch式 的语法 —— catch的{}中不能是空
二、throw式:
与try-catch式 的使用区别:
定义功能方法时,需要把出现的问题暴露出来让调用者去处理。
那么就通过throws在方法上标识。
在上述文段中,本人讲解了两个关键字——throw和throws。
现在,本人来讲解下两者之间的区别:
- throws
用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常- throw
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
这个异常对象可以是编译期异常对象,可以是运行期异常对象
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常,执行throw则一定抛出了某种异常
那么,本人来展示下如何使用throw式异常处理手段:
本人来给出一个例子:
package about_io;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Test {
public static void main(String[] args) throws SQLException {
doSomething();
}
public static void doSomething() throws SQLException {
Connection connection = null;
PreparedStatement statement = connection.prepareStatement("abc");
statement.setObject(1, "xbw");
}
}
(这里的代码是本人后期课程所要讲解的,现在无需理解,本人仅借此展示 异常的throw式的使用)
那么,我们来看一下运行结果:
可以看到,我们若使用throw式,那么当出现异常时,必定会在控制台报出,
且调用含有throw式的方法的方法,就要对该异常进行处理。
那么,关于throw式处理异常的手段,本人还有一点要说明:
说明:
- 子类在重写父类方法时,父类方法没有抛出异常,子类不能抛出
- 子类不能抛出 父类没有抛出过的异常,
- 子类方法上,抛出的异常不能比父类大,只能比父类小,或跟父类一样