Java异常处理 try catch finally 多重catch 异常分类处理

Java异常处理 try catch finally 多重catch 异常分类处理

输入两个数进行求商

使用if-else语句实现实现处理异常
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入第一个数:");
        if (sc.hasNextInt()) {
            int firstInt = sc.nextInt();
            System.out.println("请输入第二个数:");
            if (sc.hasNextInt()) {
                int secondInt = sc.nextInt();
                if (secondInt == 0) {
                    System.out.println("除数不能为0");
                } else {
                    System.out.println("商:" + firstInt / secondInt);
                }
            } else {
                System.out.println("第二个数不是int类型的数据!");
            }
        } else {
            System.out.println("第一个数不是int类型的数据!");
        }
    }
}

用if-else堵漏洞的缺点:

  • 代码臃肿、可读性差,业务代码和处理异常的代码混在一起
  • 程序员需要花费大量的经历来维护这个漏洞且很难堵住所有的漏洞。
使用try-catch处理异常
public class Test {
    public static void main(String[] args) {
        try {
            Scanner sc = new Scanner(System.in);
            System.out.println("请录入第一个数:");
            int num1 = sc.nextInt();
            System.out.println("请录入第二个数:");
            int num2 = sc.nextInt();
            System.out.println("商:" + num1 / num2);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
  • 当Java运行时系统得到一个异常对象时,它将会寻找处理这一异常事件的代码。
  • 寻找的过程从生成异常对象的代码块开始,沿着方法的调用栈逐层回溯,直到找到一个方法能够处理这种类型的异常为止。然后Java运行时系统把当前异常对象交给这个方法进行处理。这一过程称为捕获(catch)异常。
  • 如果Java运行时系统找不到可以捕获异常的方法,则Java运行时系统终止,相应的Java程序也将退出。

原理:把可能出现异常的代码放入try代码块中,然后将异常封装为对象,被catch后面的( e )中异常对象接收;接收以后,执行catch后面的{ }里面的代码,try-catch后面的代码不受影响。

  • try中没有异常,catch中代码不执行;try中有异常,catch进行捕获
    • 如果catch中异常类型和抛出的异常类型匹配:成功捕获,执行catch中的代码
    • 如果catch中异常类型和抛出的异常类型不匹配:未成功捕获,不执行catch中的代码,程序相当于遇到了无法处理的异常,程序中断,后续代码不执行

Note:try中如果出现异常且用catch捕获成功,那么try中后续的代码是不会执行的;当然没捕获成功程序中断也不会执行。如果catch捕获异常成功,程序不会中断,那么try-catch后面的代码没有影响。

catch异常处理方式

  • 佛系处理:什么都不写,什么都不做

  • 我行我素:输出自定义异常信息

  • 中规中矩:打印异常信息

    • 调用toString方法,显示异常的类名(全限定路径)
    • 显示异常描述信息对应的字符串,如果没有就显示null
    • 显示异常的堆栈信息
  • 破罐子破摔:异常抛回

对一些特定的异常可以再使用代码补救,比如被除数为0,可以在catch中再输入一次

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        //实现一个功能:键盘录入两个数,求商:
        try {
            Scanner sc = new Scanner(System.in);
            System.out.println("请录入第一个数:");
            int num1 = sc.nextInt();
            System.out.println("请录入第二个数:");
            int num2 = sc.nextInt();
            System.out.println("商:" + num1 / num2);
        } catch (Exception e) {
            /*第一种处理:什么都不写,什么都不做*/
//            第二种处理:输出自定义异常信息
            System.out.println("对不起,你的代码有问题!");
//            第三种处理:打印异常信息:
//            (1)调用toString方法,显示异常的类名(全限定路径)
            System.out.println("e:" + e);
            System.out.println("e.toString():" + e.toString());
//            (2)显示异常描述信息对应的字符串,如果没有就显示null
            System.out.println("e.getMessage():" + e.getMessage());
//            (3)显示异常的堆栈信息:将异常信息捕获以后,在控制台将异常的效果展示出来
            System.out.print("e.printStackTrace():");
            e.printStackTrace();
//            第四种处理:抛出异常:
            //throw e;
        }
        System.out.println("\n-----------try-catch后代码-----------");
    }
}

运行结果

请录入第一个数:
2
请录入第二个数:
0
对不起,你的代码有问题!
e:java.lang.ArithmeticException: / by zero
e.toString():java.lang.ArithmeticException: / by zero
e.getMessage():/ by zero
e.printStackTrace():
-----------try-catch后代码-----------
java.lang.ArithmeticException: / by zero
	at com.skprimin.cat.Test.main(Test.java:21)

try-catch后面的代码不执行的情况

  • throw抛出异常的情况
  • catch中没有正常的进行异常捕获
  • 在try中遇到return

只要将必须执行的代码(关闭数据库资源,关闭IO流资源,关闭socket资源)放入finally中,那么这个代码无论如何一定执行。即使有return,也会先执行finally后执行return。除非使用System.exit(0);终止当前的虚拟机执行

实例
public class Test{
	public static void mb_createException(){
		throw new ArrayIndexOutOfBoundsException();
	}
	public static void mb_method(){
		try{
			mb_createException();
			System.out.print("a");
		}catch(ArithmeticException e){
			System.out.print("b");
		}finally{
			System.out.print("c");
		}
		System.out.print("d");
	}
	public static void main(String args[]){
		try{
			mb_method();
		}catch(Exception e){
			System.out.print("m");
		}
		System.out.print("n");
	}
}
cmn
  1. 程序运行后先进入主函数main(),执行try语句,通过如下所示的调用生成了异常ArrayIndexOut OfBoundsException,随后在mb_method()函数中便率先开始了异常捕获机制,“a”并未输出。
  2. 而ArrayIndexOutOfBoundsException 是 Exception类的子类,按照如下的顺序向上寻找对应的catch异常处理
  3. 异常生成后首先由mb_method()处理,由于ArithmeticException与该异常无直系关系,不会输出“b”,函数中的catch无法捕获,导致mb_method()后续代码无法执行,即无法打印“d”,在草草执行finally输出"c"后本函数便结束了。
  4. 回到主函数main(),通过三层寻找终于由Exception成功捕获了ArrayIndexOutOfBounds Exception,执行catch中的代码块输出"m",成功捕获异常后后续代码得以执行,输出“n”。

多重catch处理

  • try中出现异常以后,将异常类型跟catch后面的类型依次比较,按照代码的顺序进行比对,执行第一个与异常类型匹配的catch语句
  • 一旦执行其中一条catch语句之后,后面的catch语句就会被忽略了!
  • 在安排catch语句的顺序的时候,一般会将特殊异常放在前面(并列),一般化的异常放在后面。先写子类异常,再写父类异常。
  • 在JDK1.7以后,异常新处理方式:可以并列用|符号连接:
public class Test02 {
    public static void main(String[] args) {
        try {
            Scanner sc = new Scanner(System.in);
            System.out.println("请录入第一个数:");
            int num1 = sc.nextInt();
            System.out.println("请录入第二个数:");
            int num2 = sc.nextInt();
            System.out.println("商:" + num1 / num2);
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        } catch (InputMismatchException e) {
            System.out.println("本数不是int类型的数据!");
        } catch (Exception e) {
            System.out.println("对不起,你的程序出现异常");
        } finally {
            System.out.println("----感谢您使用计算器");
        }
    }
}

异常分类

Object Throwable Error Exception IOException RuntimeException 其他异常 VirtualMachineErro 其他错误

异常又可分为检查异常和运行时异常

检查异常
  • 检查异常:防患于未然的效果,写代码时就要对代码的异常进行处理。如ClassNotFoundExceptionInstantiationException

常用的检查异常包括:

  1. IOException输入输出异常
  2. FileNotFoundException找不到指定文件的异常
  3. EOFException到达文件尾异常
  4. SQLException数据库异常
  5. ProtocolException网络协议异常
  6. SocketException Socket操作异常
处理方式
  • try-catch

    • 循环嵌套
      try {
          try {
              Class.forName("com.skprimin.excp.Test").newInstance();
          } catch (InstantiationException e) {
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              e.printStackTrace();
          }
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      }
    
    • 多重catch
      try {
          Class.forName("com.skprimin.excp.Test").newInstance();
      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
          e.printStackTrace();
      }
    
  • throws

public class Test3 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class.forName("com.skprimin.excp.Test").newInstance();
    }
}
运行时异常
  • 运行时异常:写代码时不用特意对异常进行处理,在程序运行后,自动检测,报出异常。
public class Test4 {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        System.out.println(arr.length);
        System.out.println(arr[10]);
    }
}

常用的运行时例外包括:

  1. ArithmeticException数学运算异常,比如除数为零的异常
  2. IndexOutOfBoundsException下标越界异常,比如集合、数组等
  3. ArrayIndexOutOfBoundsException访问数组元素的下标越界异常
  4. StringIndexOutOfBoundsException字符串下标越界异常
  5. IllegalArgumentException无效参数异常,比如,试图将字符串转换成一种数值,但该字符串不能转换为适当格式时,抛出该异常
  6. NullpointerException当程序试图访问一个空数组中的元素,或访问一个空对象中的方法或变量时产生的异常
posted @ 2021-08-03 23:04  SKPrimin  阅读(246)  评论(0编辑  收藏  举报