• Java的异常处理机制


    Java的异常处理机制


    简介

               Java的异常结构图

    此处输入图片的描述
    从图中观察可得:

    1. 所有的异常类是从java.lang.Exception的继承子类。
    2. Exception类是Throwable的子类。Error也是它子类之一,

    异常可能在如下几种情景下发生:

    • 用户输入数据不合法。
    • 找不到要打开的文件
    • 网络在传输中断开

    程序问题分类标准:

    • 检查型异常 在编译时期出现,也称作为编译时异常,这些异常需要程序员根据提示处理好。
      image_1clqhnb0hb741ch95j5rj9stk37.png-17.3kB
      报错信息:
      image_1clqho3htg7nufjc5n6hf9sp3k.png-23.8kB
    • 非检查型异常 又称作为“运行时异常”,常由 逻辑错误和API的错误调用导致。这类异常在编译时被忽略。
      image_1clqhpufu1fgn113etfuisj1isv41.png-12.1kB
      报错信息:
      image_1clqhq7qk7f7fol1oa0mmq1ot34e.png-16.2kB

    PS:我们可以发现,检查型异常在编写时就会有报错信息让你修改,并且编译没有通过。而运行时异常通过了编译,是在运行时报的错。

    • Errors 一般是由运行环境产生的,在编译时期觉察不到,这类问题一般程序员处理不了。
      注:异常可以处理,但是errors是不能处理,也就是说遇到error,程序一般无法自动恢复运行。
      image_1clqi22cn1t50f9d1ml2156u1ps96o.png-14.9kB
      报错信息:
      image_1clqi0v2v1eq21jlk10qa1nl9j9a5b.png-18.6kB
       

    关于异常处理:我们一般只捕捉处理编译时异常,而对于运行时异常,因为它们常常是api调用方式不对(参数为空等),我们不会捕捉,而是让程序员发现后进行代码修改,如果强行处理运行时异常,可能会导致逻辑错误更加严重。并且,运行时异常占了绝大多数,处理起来会很麻烦,降低代码阅读性。尽管如此,的确有些特殊情况让我们处理,比如空指针异常。总之,不管你是怎么声明异常,想让你程序运行下去就用检查型异常,想让它停止,就用运行时异常。


    常见的异常

    1.非检查型异常:
    image_1clqhgho119oe1bfup8otks1emo20.png-126.5kB
    2.检查型异常:
    image_1clqhit1o1c221m9f18osg1m120k2d.png-49.4kB
    表格摘自:https://www.runoob.com/java/java-exceptions.html


    异常的捕捉方法
    1.try catch 语句使用

    public static void main(String[] args){
            try{
                int num[] = {1, 2, 3, 4};
                System.out.println(num[5]);
                System.out.println("这是异常后的位置");
            }catch (ArrayIndexOutOfBoundsException e){
                System.out.println("异常发生,处理异常中---");
            }
            System.out.println("异常处理后---");
        }
    输出:
        异常发生,处理异常中--- 
        异常处理后---
    

    注意:try块中发生异常后,异常位置之后的代码不会被执行,异常一旦发生,就会马上去catch中找对应的异常处理方法。

    2.多个catch捕捉多个异常 和 一个catch捕捉多个异常

        try {
        } catch (IndexOutOfBoundsException e) {
                System.err.println("IndexOutOfBoundsException: " + e.getMessage());
        } catch (IOException e) {
                System.err.println("Caught IOException: " + e.getMessage());
        }
    
        //这个时候,里面的引用是隐式的final类型,ex不能改指向。
        catch (IOException|SQLException ex) {
            logger.log(ex);
            throw ex;
        }
    

    3.throws/throw 关键字
    二者使用异同?

    • throws写在函数签名末尾,表明了这个函数可能会出现的异常,throw在函数中确切地抛出一个异常。
    • throws后面接异常类名称,throw后面接异常实例
    • throws后面可以接多种异常类名,throw每次只能抛出一个异常。
    • 出现异常后,二者都会抛给上一层,让上一层处理。

    代码示例:

    throw 使用样例:
    public class Example1{  
       void checkAge(int age){  
        if(age<18)  
           throw new ArithmeticException("Not Eligible for voting");  
        else  
           System.out.println("Eligible for voting");  
       }  
       public static void main(String args[]){  
        Example1 obj = new Example1();
        obj.checkAge(13);  
        System.out.println("End Of Program");  
       }  
    }
    
    throws 使用样例:
        public void writeList() throws IOException, IndexOutOfBoundsException {}
    

    使用throws的好处:
    1.虽然我们可以使用try catch处理异常,但是如果你有多个函数会抛出异常,你得为每个函数都写一个try catch,那样很繁琐,所以我们就将异常统一交给调用外层来处理。
    2.当使用throws关键字,你调用该方法编译器会提醒你处理异常,不然报错,这样提升了代码的准确性。

    使用总结:
    确定会出现异常位置,你可以用throw抛出去。
    如果不想自己抛,用throws方法,会帮你把异常抛给函数调用者。

    4.finally关键字
    从字面上理解,finally是“最后”的意思,在代码中,我们可以理解为“收尾”工作,所谓收尾,就像平时举办活动一样,活动中不管有没有出现异常都会收尾,顺序也肯定是在最后执行。
    通常,我们会使用一些streams,connections一些资源接口,在使用完毕后我们要在finally块中收尾显示完成关闭接口。

    public static void main(String[] args){
            try{
                int num[] = {1, 2, 3, 4};
                System.out.println(num[5]);
                System.out.println("这是异常后的位置");
            }catch (ArrayIndexOutOfBoundsException e){
                System.out.println("异常发生,处理异常中---");
            }finally {
                System.out.println("异常处理收尾收尾---");
            }
            System.out.println("异常处理后---");
        }
    输出:
        异常发生,处理异常中---
        异常处理收尾收尾---
        异常处理后---
    

    一个语法糖try-with-resources
    之前我们讲到finally的显示完成关闭接口,在java7之后采用了一种新的方式,可以自动帮我们完成连接的关闭。
    方法:
    我们只要在try的括号内创建这个reader的对象就行

    try(FileReader fr = new FileReader("file path")) {
       // use the resource
       } catch () {
          // body of catch 
       }
    }
    

    要使用这个语法糖,必须满足如下几个条件:

    1. 使用的类必须实现了 AutoCloseable 接口;
    2. 你可以在括号里面实例多个资源对象;
    3. 当你实例化了多个对象,关闭时的顺序和声明时的顺序相反
    4. 该resource在try块之前实例化,并且里面的resource引用是隐式的final类型,除此以外并无区别

    注意点

    1. try后面必定有catch语句或者finally语句中的一个。
    2. try-catch-finally语句之间不能参杂其他代码,必须是紧跟着。

    自定义异常

    系统定义的异常太少,不满足你的需求,你也可以自定义异常。但是要注意如下几点:

    1. 所有自定义异常必须间接或者直接是Throwable类的子类。
    2. 如果要写一个检查型异常类,继承Exception类。
    3. 如果写一个运行时异常类,需要继承RuntimeException类。
  • 相关阅读:
    Android实现通过浏览器点击链接打开本地应用(APP)并拿到浏览器传递的数据(转)
    保存图片文件到本地
    android ScrollView中嵌套GridView,ListView只显示一行的解决办法
    蒙版提示页(添加新功能后的一种提示)
    C和指针 第三章--数据
    *(ptr++) += 123
    优先级队列-堆
    单链表相关(一)
    字符间的距离-动态规划
    和最大的连续子数组
  • 原文地址:https://www.cnblogs.com/gujiewei/p/9670569.html
Copyright © 2020-2023  润新知