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

    一、什么是异常

    java的基本理念是“结构不佳的代码不能运行”,在编译期间并不能发现所有的错误,余下的问题必须在运行阶段解决。异常处理是java中唯一正式的错误报告机制。异常情形是指阻止当前的方法或者作用域继续执行的问题。在java中通过异常处理机制来处理程序运行期间出现的错误,提升程序的健壮性。

    java中与使用其他对象一样,在堆上创建对象来处理异常。针对不同的异常new出不同的异常对象。异常对象的根类是java.lang.Throwable类。在Java中定义了很多异常类(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),这些异常类分为两大类:Error和Exception。Error即无法处理的异常,一旦发生终止程序的运行。Exception,是我们可以处理的异常。Exception包括hecked exception和unchecked exception两类。

    unchecked exception(非检查异常),也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。

    checked exception(检查异常),也称非运行时异常(运行时异常以外的异常就是非运行时异常),java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。

    在Java中,异常类的结构层次图如下图所示:

    在Java中,所有异常类的父类是Throwable类,Error类是error类型异常的父类,Exception类是exception类型异常的父类,RuntimeException类是所有运行时异常的父类,RuntimeException以外的并且继承Exception的类是非运行时异常。常见的异:NullPointerException、IndexOutOfBoundsException、ArrayIndexOutOfBoundsException等等。

    异常匹配:抛出异常的时候,异常处理系统会按照代码的书写顺序找出“最近”的处理程序,找到匹配的处理程序后,则认为异常得到了处理,然后不再继续查找。查找的时候并不要求抛出的异常同处理程序声明的异常完全匹配,派生类对象匹配其基类的处理程序。那么Exception则是所有的异常类的基类,即可捕获所有的异常。

    把“受检查异常“转换为“不受检查的异常”,可以在捕获到的受检查异常后,再次抛出一个不受检查的异常。

    二、异常的处理处理方式

    1、捕获

    异常的捕获主要使用try和catch关键字,被try块包围的代码,表示这段代码中可能出现异常,一旦发生异常,异常对象则被cathch捕获,然后在catch块中进行处理。如下:

     1 public class Demo5 {
     2     public static void main(String[] args) {
     3         try {
     4             int i=10/0;
     5             System.out.println(i);
     6         } catch (ArithmeticException e) {
     7             e.printStackTrace(System.err);
     8         }
     9     }
    10 }
    11 输出的结果:
    12 java.lang.ArithmeticException: / by zero
    13     at com.sun.lp.demo.Demo5.main(Demo5.java:18)

    2、抛出

    抛出是异常处理的另外一种方式,顾名思义,一旦发生异常,将异常抛出去,处理的关键字是throw和throws,如下:

    public class Demo5 {
        public void test() throws Exception{
            try {
                int i = 10/0;
                System.out.println(i);
            } catch (Exception e) {
                //捕获到异常,不处理,将其抛出
                throw e;
            }
            
        }
        public static void main(String[] args) {
            try {
                Demo5 demo5 = new Demo5();
                demo5.test();
            } catch (Exception e) {
                e.printStackTrace(System.err);
            }
            
            
        }
        
    }

    结果输出:

    java.lang.ArithmeticException: / by zero
        at com.sun.lp.demo.Demo5.test(Demo5.java:6)
        at com.sun.lp.demo.Demo5.main(Demo5.java:17)

    三、自定义异常

    不拘泥于java中已有的异常对象,java提供的异常体系不可能预见所有的异常。所以java提供自定义异常的途径。自定义异常必须从已有异常类的基础上继承和拓展。建立新的异常最简单的方法是让编译器为你产生默认的构造器

     1 public class Demo {
     2 
     3     public void test() throws MyException{
     4         System.out.println("Exception is from test()");
     5         throw new MyException();
     6     }
     7     
     8     public static void main(String[] args) {
     9         try {
    10             Demo demo = new Demo();
    11             demo.test();
    12         } catch (Exception e) {
    13             System.out.println("get a Exception");
    14             e.printStackTrace(System.err);
    15         }
    16         
    17     }
    18     
    19 }
    20 
    21 class MyException extends Exception{
    22     MyException(){
    23         System.out.println("自定义异常类");
    24     }
    25 }

    输出结果:

    Exception is from test()
    自定义异常类
    get a Exception
    com.test.demo.MyException
        at com.test.demo.Demo.test(Demo.java:5)
        at com.test.demo.Demo.main(Demo.java:11)
    四、使用finally进行清理
    对于一些代码,无论try块中的异常是否抛出,它们都能执行,达到这个效果可以使用finally子句。finally子句总能运行。
     1 public class FinallyDemo {
     2     public static int count=0;
     3     public static void main(String[] args) {
     4         while(true){
     5             try {
     6                 if(count++==0)
     7                     throw new SimpleException();
     8                 System.out.println("No Exception");
     9             } catch (SimpleException e) {
    10                 System.out.println("get a SimpleException");
    11             }finally{
    12                 System.out.println("finally 子句执行");
    13                 if(count==2) break;
    14             }
    15         }
    16     }
    17 }
    18 class SimpleException extends Exception{
    19     SimpleException(){
    20         super();
    21     }
    22 }

    输出结果:

    get a SimpleException
    finally 子句执行
    No Exception
    finally 子句执行

    五、几个关键字的使用

    1.try关键字用来包围可能会出现异常的逻辑代码,它单独无法使用,必须配合catch或者finally使用。三个块执行的顺序为try—>catch—>finally。Java编译器允许的组合使用形式只有以下三种形式:

    try...catch...;       try....finally......;    try....catch...finally...

    2.throws和thow关键字

    throws出现在方法的声明中,表示该方法可能会抛出的异常,然后交给上层调用它的方法程序处理,允许throws后面跟着多个异常类型。

    throw一般用于程序出现某种逻辑,程序员主动抛出指定的异常对象,throw主要出现在方法体中,抛出的异常对象可以进行向上转型。

    3.由于垃圾回收机制的存在,finally主要是把除内存资源之外的资源恢复到它们的初始状态,例如:关闭文件流,网络联机,关闭数据库连接等等。

    六、异常使用指南

    1)在恰当的级别处理问题(在知道如何处理的情况下才捕获异常)

    2)解决问题并重新调用产生异常的方法

    3)进行少许的修补,然后绕过异常发生的地方继续执行

    4)用别的数据进行计算,以代替方法预计会返回的值

    5)把当前运行环境下能做的事情尽量做完,然后把相同的异常抛出到更高层

    6)把当前运行环境下能做的事情尽量做完,然后把不相同的异常抛出到更高层

    7)终止程序

    8)进行简化

    9)让类库和程序更安全。

  • 相关阅读:
    【QT】Linux下安装QT开发环境
    【C#】Winform嵌入dll到exe中
    使用maven插件构建docker镜像并推送到阿里镜像仓库
    蓝牙耳机连接 win10音量异常
    max virtual memory areas vm.max_map_count [65530] is too low
    docker 安装 confluence
    jenkins docker push脚本
    docker 删除指定名称的所有容器
    docker 安装 xxl-job-admin
    docker 安装 sentinel
  • 原文地址:https://www.cnblogs.com/liupiao/p/9249232.html
Copyright © 2011-2022 走看看