为什么要进行异常处理
下面这段代码能否正常执行
- public class DemoCalc {
- public static void main(String[] args) {
- int a=0;
- int b=0;
- int c=a/b;
- System.out.println("运算结果为:"+c);
- }
- }
结果是我们在控制台中看到一段错误提示, 那是因为除数不能为 0. 异常就是在程序运行过程中发生的不正常事件, 会中断运行的程序.
Java 使用了异常处理机制为程序提供了错误处理的能力, 在程序中预先设置好对付异常的处理办法, 待程序发生异常时对异常进行处理, 处理完毕后, 程序便可以继续运行.
下面来看一下 Java 中是如何进行异常处理的
如何进行异常处理
Java 的异常处理是通过 5 个关键字实现的: try,catch,finally,throw,throws
关键字 | 作用 |
---|---|
try | 执行可能产生异常的代码 |
catch | 捕获异常 |
finally | 无论是否发生异常,代码总能执行 |
throws | 声明方法要抛出的异常 |
throw | 手动抛出异常 |
常见异常及异常分类
Throwable 是 Java 中所有错误和异常的父类
Error 类: Throwable 的子类, 仅靠程序本身无法恢复的严重的错误.
Exception 类: Throwable 的子类, 由 Java 应用程序抛出和处理的非严重错误
RuntimeException 类: Exception 的子类, 运行时异常, 不要求程序必须做出处理.
Checked 异常: Exception 的子类, 程序必须处理该类异常.
常见异常类型
异常类型 | 说明 |
---|---|
Exception | 异常层次结构的父类 |
ArithmeticException | 算数错误情形,如以零作除数 |
ArrayIndexOutOfBoundsException | 数组下标越界 |
NullPointerException | 尝试访问 null 对象成员 |
ClassNotFoundException | 不能加载所需的类 |
IllegalArgumentException | 方法接收到非法参数 |
ClassCastException | 对象强制类型转换出错 |
NumberFormatException | 数字格式转换异常,如把 "abc" 转换成数字 |
try-catch
语法:
- public void method(){
- try{
- // 代码段 1
- // 可能产生异常的代码段
- // 代码段 2
- }catch(异常类型 ex){
- // 对异常进行处理的代码段
- }
- // 代码段
- }
try-catch 块捕获异常有三种情况:
1,try 块中没有任何异常, try 中正常, catch 不会执行, 正常执行 try-catch 后的代码.
2,try 块中可能发生异常的代码段发生异常, 代码段 2 不会执行, 而是执行 catch 中异常处理的代码, 正常执行 try-catch 后的代码.
catch 中异常类型的 printStackTrace() 方法能进行堆栈跟踪显示出程序运行到当前类的执行流程, 异常堆栈信息中包含了异常的类型及异常出现的位置.
3, 异常类型不匹配, 程序将中断. 比如 try 产生的异常为 ArithmeticException,catch 却用了 ClassCastException.
在控制台中接收数字做除法运算
- import java.util.Scanner;
- public class DemoInput {
- public static void main(String[] args) {
- Scanner input=new Scanner(System.in);
- try{
- System.out.println("请输入被除数 (整数):");
- int a=input.nextInt();
- System.out.println("请输入除数 (整数):");
- int b=input.nextInt();
- int c=a/b;
- System.out.println("结果:"+c);
- }catch(Exception ex) {
- ex.printStackTrace();
- }
- System.out.println("程序结束");
- }
- }
- try-catch-finally
语法:
- public void method(){
- try{
- // 可能会发生异常的代码
- }catch(异常类型 ex){
- // 异常处理
- }finally{
- // 无论如何都要执行的代码
- }
- }
finally 块: 是否发生异常都执行
finllay 块不执行的唯一情况: 之前的代码中执行了 System.exit(1); 退出虚拟机
try-catch-finally 的使用
- import java.io.FileNotFoundException;
- import java.util.Scanner;
- public class DemoInput {
- public static void main(String[] args) {
- Scanner input=new Scanner(System.in);
- try{
- System.out.println("请输入被除数 (整数):");
- int a=input.nextInt();
- System.out.println("请输入除数 (整数):");
- int b=input.nextInt();
- int c=a/b;
- System.out.println("结果:"+c);
- }catch(Exception ex) {
- ex.printStackTrace();
- }finally {
- System.out.println("感谢您的使用");
- }
- System.out.println("程序结束");
- }
- }
如果在 try 块或 catch 块中有 return 语句, finally 是否还会执行? 运行下面代码断点调试观察结果.
- public class TestReturn {
- public static void main(String[] args) {
- try {
- int a=1+1;
- System.out.println("try 执行");
- return;
- } catch (Exception e) {
- System.out.println("catch 执行");
- }finally {
- System.out.println("finally 执行");
- }
- }
- }
try 块或 catch 块中可以有 return 语句, 如果有 return 语句会先执行 finally 最后再执行 return.
多重 catch
try 块中可能会发生多种异常, 如果要不同的异常进行不同的处理, 需要使用多重 catch 进行处理.
语法:
- public void method(){
- try{
- // 可能发生异常的代码段
- }catch(异常类型 1 e){
- // 对异常类型 1 进行的处理的代码段
- }catch(异常类型 2 e){
- // 对异常类型 2 进行的处理的代码段
- }catch(异常类型 n e){
- // 对异常类型 n 进行的处理的代码段
- }
- }
当 try 块中发生异常后, 会逐个与 catch 中的异常类型进行匹配, 匹配成功后, 进入对应的 catch 进行异常处理, 处理完成后不再进入其他 catch, 程序继续执行.
排列 catch 语句的顺序是: 先子类后父类
发生异常时按顺序逐个匹配
只执行第一个与异常类型匹配的 catch 语句
将之前的代码 DemoInput.java 改造成多重 catch
- import java.io.FileNotFoundException;
- import java.util.InputMismatchException;
- import java.util.Scanner;
- public class DemoInput {
- public static void main(String[] args) {
- Scanner input=new Scanner(System.in);
- try{
- System.out.println("请输入被除数 (整数):");
- int a=input.nextInt();
- System.out.println("请输入除数 (整数):");
- int b=input.nextInt();
- int c=a/b;
- System.out.println("结果:"+c);
- }catch(InputMismatchException e) {
- System.out.println("输入的数有误!");
- }catch(ArithmeticException e) {
- System.out.println("除数不能为 0");
- }catch(Exception ex) {
- System.out.println("发生未知异常");
- }finally {
- System.out.println("感谢您的使用");
- }
- System.out.println("程序结束");
- }
- }
声明异常 throws
如果一个方法体内抛出了异常如何通知调用者, 可以在方法上声明异常.
- public class TestThrows {
- // 声明异常, 多个异常可以用逗号隔开
- public void test()throws Exception,ClassNotFoundException{
- // 可能会发生异常的代码
- }
- }
处理方式一: 调用者处理异常
- public static void main(String[] args) {
- TestThrows t=new TestThrows();
- try {
- t.test();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
处理方式二: 调用者继续声明异常
- public static void main(String[] args) throws ClassNotFoundException, Exception {
- TestThrows t=new TestThrows();
- t.test();
- }
main 方法继续声明异常, 调用者就变成虚拟机了, 发生异常则按默认方式处理, 打印出来.
抛出异常 throw
除了系统自动抛出的异常外, 有些问题需要程序员自行抛出异常
- public class TestThrow {
- public void inputAge(int age) throws Exception {
- if (age<1) {
- throw new Exception("还有这种年龄?");
- }
- }
- public static void main(String[] args) {
- TestThrow t=new TestThrow();
- try {
- t.inputAge(-1);
- } catch (Exception e) {
- System.out.println("年龄有误:"+e.getMessage());
- }
- }
- }
自行抛出异常后, 还需要在方法上声明异常
来源: https://www.cnblogs.com/AIThink/p/9846642.html