• 理解Java异常处理机制


    版权声明:本文为博主原创文章,转载请注明出处。

    1.以下是异常的基本介绍:Java异常层次结构图 如下

           Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类,结构如上图(以上结构图中的子类异常并不是所有的,只是标注了一些重要的常见的异常)。

           Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。

           大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(VirtualMachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。

           Exception(异常):是程序本身可以处理的异常。

           Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。

      Exception 和 RuntimeException 的区别:

        1.Exception 表示程序运行过程中可能出现的非正常状态,RuntimeException表示虚拟机非通常操作中可能遇到的异常,是一种常见运行错误。Java编译器要求方法必须声明抛出可能发生的非运行时异常,但并不要求必须声明抛出未被捕获的运行时异常,即 Exception 定义了必须处理的异常,而 RuntimeException 定义的异常可以选择性的进行处理。

        2.RuntimeException 是 Exception 的子类。

    2.异常的处理

      在Java中,如果某个方法抛出异常,既可以在当前方法中进行捕捉,然后处理该异常,也可以将该异常向上抛出,由方法调用者来处理。

      a>.Java的异常捕获结构由try、cache和finally3个部分组成,例如:

     1 try {
     2     // 可能会抛出异常的代码块
     3     int result = 2 / 0;
     4     System.out.print("运算结果:" + result);
     5 } catch (ArithmeticException e) {
     6     // 对异常1的处理
     7     System.out.print("出现了算术异常");
     8 } catch (Exception e) {
     9     // 对异常2的处理
    10     // 以此类推还可以加各种异常的处理,由上图结构可知,Exception是运行时异常的父类,所以所有异常都能被exception接收,一般情况下如果没有对特定异常的特殊处理catch写exception就可以了
    11     e.printStackTrace();// 打印异常的堆栈信息
    12 } finally {
    13     // 程序代码块 -- 异常处理结构最后处理的部分
    14 }

      try 语句块:用于执行可能有异常的代码块。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。

      catch语句块:一个try catch结构中可以有多个catch,捕获不同的异常做不同的异常处理,没有特殊需求,一般用一个Exception就可以了

      异常捕获范围问题:多个catch的时候,所有捕获范围小的异常必须放在捕获范围大的异常之前,否则程序在编译时就会出现错误提示。参考异常结构图,例如上面的代码段,把 Exception 和 ArithmeticException 交换位置,Exception在前, 由异常结构图可知,Exception是ArithmeticException 的父类,所以有算术异常的时候,Exception也可以捕获该异常,后面添加 ArithmeticException 已经没有用了,故而会直接编译报错。

      finally语句块:一个try catch结构中finally可写可不写,有finally语句块的时候,表示不管是否有异常该代码块一定会被执行,一般常用于输入流、输出流关闭。

      注意:面试常被问的地方:如果在try里面有return,finally是否执行答:finally语句块依旧会被执行,在try语句块中的return之前执行

      以下4中特殊情况finally不会执行:

      • 在finally语句块中发生了异常
      • 在前面的代码中使用了System.exit()退出程序
      • 程序所在线程死亡
      • 关闭CPU

      b>.throws,throw

      某个方法可能会发生异常,但不想在当前方法中处理这个异常,则可以使用 throwsthrow 关键字在方法中抛出异常。

      throws关键字通常被应用在声明方法时,用来指定方法可能抛出的异常(多个异常可用逗号分隔 ),语法如下:

     1 public static void main(String[] args) {
     2     try{
     3         test();
     4     }catch(ArithmeticException e){
     5         System.out.print("test()方法抛出算术异常");
     6     }
     7 }
     8     
     9 public static void test() throws ArithmeticException{
    10     int result = 3/0;
    11 }

      使用throws 关键字将异常抛给上一级以后,如果不想处理该异常,可以继续向上抛出,如果main() throws Exception 就相当于交给JVM进行异常处理。

      throw 关键字通常用于方法体中,并且抛出一个异常对象程序执行到throw语句时立即终止,它后面的语句都不执行。

    1 public static void main(String[] args) {
    2    try {
    3       throw new Exception("抛着玩的");
    4     } catch (Exception e) {
    5         e.printStackTrace();
    6     }
    7 }
    程序运行结果:
    java.lang.Exception: 抛着玩的
        at test.TestException2.main(TestException2.java:11)

      由于存在了throw关键字,本程序会手工抛出一个异常类的实例化对象,而此时程序必须使用 try...catch 语句进行处理,或者在方法上增加一个throws声明,否则程序会编译出错。

      throw 和 throws 的区别:

        throw:用户手工抛出异常类的实例化对象;

        throws:用于方法的声明上,表示此方法不处理异常,而将异常

      c>.自定义异常

      使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户只需继承Exception类即可自定义异常类。

      在程序中使用自定义异常类,大体可分为以下几个步骤。
      (1)创建自定义异常类。
      (2)在方法中通过throw关键字抛出异常对象。
      (3)如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
      (4)在出现异常方法的调用者中捕获并处理异常。

     1 public class MyException extends Exception { // 定义异常类
     2     public MyException(String errMessage){
     3         super(errMessage);
     4     }
     5 }
     6 
     7 public static int avg(int num1, int num2) throws MyException {
     8     if (num1 < 0 || num2 < 0) {
     9         throw new MyException("不可以使用负数");
    10     }
    11     if (num1 > 100 || num2 > 100) {
    12         throw new MyException("数值太大了");
    13     }
    14     return (num1 + num2) / 2;
    15 }
    16 
    17 public static void main(String[] args) {
    18     try {
    19         int result = avg(103, 150);
    20         System.out.print(result);
    21     } catch (MyException e) {
    22         System.out.print(e);
    23     }
    24 }

    运行结果:
      test.MyException: 数值太大了

    3.常见异常类

    • NullPointerException   空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。
    • ClassCastException    类型转换异常
    • ClassNotFoundException  未找到相应的类异常
    • ArithmeticException    算术异常
    • ArrayIndexOutOfBoundsException  数组索引越界异常
    • ArrayStoreException  数组中包含不兼容的值抛出的异常
    • SQLException   操作数据库异常类
    • NoSuchFieldException   字段未找到异常
    • NoSuchMethodException   方法未找到抛出的异常

    • NumberFormatException    字符串转换为数字抛出的异常
    • NegativeArraySizeException    数组长度为负异常
    • StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
    • IOException  操作输入流和输出流时可能出现的异常
    • IllegalArgumentException    非法参数异常
    • InstantiationException  当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
    • ArrayStoreException    数组中包含不兼容的值抛出的异常
    • SecurityException    安全性异常
    • EOFException      文件已结束异常
    • FileNotFoundException     文件未找到异常
    • NumberFormatException      字符串转换为数字抛出的异常
    • IllegalAccessException     不允许访问某类异常
  • 相关阅读:
    docker容器跑tomcat遇到的坑
    PCL 编程多个点云合成
    PCL 常用小知识
    PCL点云库中的坐标系(CoordinateSystem)
    Ubuntu14.04(64位)下gcc-linaro-arm-linux-gnueabihf交叉编译环境搭建
    Windows cmd 快捷操作
    #Pragma Pack与内存分配
    线段上的整数点个数
    基于PCL绘制模型并渲染
    rosbag数据记录及转换图片、视频
  • 原文地址:https://www.cnblogs.com/Jenny-sider/p/8330470.html
Copyright © 2020-2023  润新知