zoukankan      html  css  js  c++  java
  • Java 异常处理

    当程序运行出现意外情况时,系统会自动生成一个Exception对象来通知程序。

    Exception(异常)、Error(错误)都继承自Throwable。

    1 try{
    2             //可能出错的代码
    3         }
    4         catch(XxxException e){
    5             System.out.println(e.getMessage());  //处理异常的代码
    6         }
    7         finally {
    8             //必须要关闭的资源
    9         }

    try是必须的,catch、finally可选,但必须出现其中之一。

    try、catch代码块的{   }均不能省略,即使只有一行代码也不能省略{   }。

    try中声明的变量是局部变量,只在try代码块中有效。

    1 try{
    2             //......
    3         }
    4         catch(NullPointerException e){
    5             System.out.println(e.getMessage()); 
    6         }
    7         catch(Exception e){
    8             System.out.println(e.getMessage());
    9         }

    可以同时用多个catch捕获多个异常,但必须小异常在前,大异常在后(子类异常在前,父类异常在后)。

    1 try{
    2             //......
    3         }
    4         catch(NullPointerException|IndexOutOfBoundsException e){
    5             //System.out.println(e.getMessage());
    6         }

    可在一个catch中捕获多种异常,但这些异常必须是不同类型的,就是说不能有交集。异常类用 | 分开即可。

    catch代码块中常用的异常处理方式:

    1    System.out.println(e.getMessage());   //输出该异常的描述信息
    2    System.out.println(e.getStackTrace());  //输出该异常的跟踪栈信息
    3   e.printStackTrace(); //直接输出异常跟踪栈的信息,本身就是一个输出方法,不必写sout

    GC只负责heap中对象的回收,程序中打开的物理资源,比如数据库连接、网络连接、磁盘文件等,都必须手动关闭。一般在finally中显式回收物理资源,以确保物理资源一定会被回收。

    不管try代码块是否出现异常,不管被执行的是哪个catch代码块,甚至在try、catch中执行了return语句,finally代码块都一定会被执行,除非在try或者catch中调用了退出JVM的方法。

    Java9自动关闭资源的try语句:

     1     try(
     2         //在()中写要打开的资源
     3         FileOutputStream fos=new FileOutputStream("a.txt");
     4         ) {
     5         //在try的{ }中使用打开的资源,当try{  }中的语句执行完毕时,会自动关闭()中打开的资源
     6         fos.write("ok".getBytes());
     7         
     8       }
     9       catch(Exception e){
    10           e.getMessage();
    11       }

    我们也可以不使用try、catch处理异常,而直接把异常抛给上一级调用者:

    1  public void getReault() throws Exception{   //在定义方法是不指定异常处理方式,而是使用throws把异常抛出给上一级调用者,由上一级调用者处理
    2         //......
    3     }

    上一级调用者可以使用try、catch来处理,也可以throws抛给自己的上一级调用者。

    如果main()也使用throws抛出异常,main()抛出的异常会被JVM捕获,由JVM处理,JVM默认的处理方式是:打印异常的跟踪栈信息,终止程序运行。

    可以抛出多个异常,用逗号隔开即可。

    当程序出现异常时,系统会自动抛出异常,我们也可以手动抛出异常:

    1 int a,b;
    2         //.....
    3         try{
    4             if(b==0)
    5                 throw new Exception("除数不能为0!");  //抛出异常时,会终止try{  }中throw后面代码块的执行,直接跳到对应的catch执行
    6             System.out.println("a/b="+a/b);
    7         }catch (Exception e){
    8             System.out.println(e.getMessage());   //捕获并处理我们自己抛出的异常
    9         }
    10    //后面的代码仍会继续执行

    比如下棋时,先检测该点是否已有子,若已有子,自己抛出一个异常,在catch中捕获这个异常,输出提示“该点已有子,不能再落子”,接着继续执行catch代码块后面的代码(结束本次循环,等待用户输入落子点坐标)。

    不管是系统自动抛出的异常,还是我们手动throw抛出的异常,处理方式都一样:终止try{  }中其余部分代码的执行,跳到对应的catch块执行后继续执行catch块后面的代码。

    由于前面的结果有问题,catch后面正常的代码块往往也会出现问题,程序往往会抛出异常,一级级抛到JVM,打印跟踪栈信息,终止程序。比如try中做一个除法,try后面要使用商,执行try的时候除数为0,抛出异常,转到对应catch执行,然后继续执行catch后面的代码块,但商有问题,正常代码块的执行也会出现异常。

    也可以这样:

    1 public static void main(String[] args) throws Exception {  //抛给上一级调用者
    2         int a,b;
    3         //......
    4         if(b==0)   //不使用try、catch
    5             throw new Exception("除数不能为0!");  //可以不在try中抛出异常,这样就可以不用catch处理我们抛出的异常,而是直接抛给上一级调用者,由上一级调用者处理
    6         System.out.println("a/b="a/b);
    7     }

    throw抛出的是一个异常类的实例,而不是异常类,所以要new一个异常类的实例。(参数为异常类的message)

    在大型企业级应用中,常常结合使用try、throw,catch做一部分处理,再把这个异常抛给上一级调用者,上一级调用者再做一些处理。

     1 public static void main(String[] args) throws Exception {  //抛给上一级调用者
     2         //.....
     3        try{
     4            //.....
     5        }
     6        catch (Exception e){
     7            //当前catch块做一些处理,比如在日志中记录异常
     8            //.....
     9            
    10            //然后再把这个异常抛给上一级调用者,由上一级调用者继续处理,需要在本方法的函数头用throws声明一下。当前方法则继续执行catch代码块后面部分
    11            throw new Exception(".....");
    12        }
    13        //.....
    14     }

    我们也可以自定义异常,自定义异常必须继承Exception基类。可以直接继承,也可以继承Exception的子类(间接继承)。

    异常转译:

    通常我们不把底层的原始异常直接传给用户,而是先捕获异常,再抛出一个新异常,新异常包含用户提示信息,由上一级调用者处理。

     1 public static void main(String[] args) throws XxxException {  //需要在此处声明,抛给上一级调用者
     2         //.....
     3        try{
     4            //.....
     5        }
     6        catch (XxxException e){
     7            //把原始异常记录下来,留给管理员查看
     8            //.....
     9 
    10            //抛出新异常,由上一级调用者处理。转译原始异常的信息,提示信息用户友好。
    11            throw new XxxException("您的xxx不合法");   
    12        }
    13        //.....
    14     }

    捕获一个异常,然后接着抛出一个异常,并把原始的异常信息保存下来,这是典型的链式处理(23种设计模式之一:职责链模式,也称为异常链)。

    异常跟踪栈:

    异常对象的printStackTrace(),可打印异常的跟踪栈信息,开发者可据此找到异常的源头,跟踪异常一路触发的过程。

    程序运行时,经常会发生一系列的方法调用,形成方法调用栈。异常的传播方向和方法调用的方向相反,总是由最内部被调用的方法传播到最外部的方法调用( 一般是main(),或者Thread类的run()——多线程情况)。

    调试时,我们经常在catch中只输出/打印异常的原始信息,这方便调试,但发布程序时要避免输出异常的原始信息,而是要转换为对异常的适当处理。

    不要忽略异常,要对异常做一些有用的处理,而不仅仅是在catch中打印异常信息、或者catch块直接为空。

    不要在try中放置大量的代码,因为try中代码越多,出错的可能性越大,代码太多,出错后不好分析异常原因。

    可以把大块的try分割为多个可能出现异常的小块的try,分别捕获并处理:

     1 try{
     2            
     3        }
     4        catch (XxxException e){
     5            
     6        }
     7         try{
     8 
     9         }
    10         catch (XxxException e){
    11 
    12         }
    13         try{
    14 
    15         }
    16         catch (XxxException e){
    17 
    18         }
  • 相关阅读:
    萌新向Python数据分析及数据挖掘 第三章 机器学习常用算法 第三节 梯度下降法 (上)理解篇
    萌新向Python数据分析及数据挖掘 第三章 机器学习常用算法 第二节 线性回归算法 (下)实操篇
    萌新向Python数据分析及数据挖掘 第三章 机器学习常用算法 第二节 线性回归算法 (上)理解篇
    萌新向Python数据分析及数据挖掘 第三章 机器学习常用算法 第一节 KNN算法 (下)实操篇
    萌新向Python数据分析及数据挖掘 第三章 机器学习常用算法 第一节 KNN算法 (上)理解篇
    萌新向Python数据分析及数据挖掘 第二章 pandas 第五节 Getting Started with pandas
    Oracle数据库安装和授权
    c# 如何获取JSON文件以及如何获取Config文件(framework 和 net .Core)
    C#Core查询数据库存储EXCEL文件
    如何在WINDOW系统下编译P12证书制作
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/10897634.html
Copyright © 2011-2022 走看看