• java中的异常处理机制


    一、java异常总结:

    异常就是程序运行时出现不正常运行情况

    1.异常由来:

    通过java的类的形式对现实事物中问题的描述,并封住成了对象

    其实就是java对不正常情况描述后的对象体现

    2.对于问题的划分有两种:一种是严重的问题,一种是非严重的问题

    对于严重的,java通过Error类来描述   

                      对于Error一般不编写针对性的代码对其进行处理

    对于非严重的,java通过Exception类来描述

                      对于Exception可以使用针对性的处理方式进行处理

    3.常见的异常有:数组角标越界异常,空指针异常……

    4.无论Error或者Exception都有一些共性的内容。

    比如:不正常情况的消息,引发原因等。

    Throwable   //父类(下面两个类相同的共性抽取出来的)

              |--Error

              |--Excption   //两个子类(里面定义了很多问题(异常出现))             /*父类名作为子类后缀名*/

    实例1:出现异常示例

     1 class Demo  
     2 {
     3     public int div(int x,int y)
     4     {
     5         return x/y;
     6     }
     7 }
     8 
     9 
    10 class ExceptionDemo
    11 {
    12     public static void main(String args[])
    13     {
    14         Demo d=new Demo();
    15         int x=d.div(4,0);    //0作为除数
    16         System.out.println("x="+x);
    17         System.out.println("over");
    18     }
    19 }

    运行结果:

    Exception in thread "main" java.lang.ArithmeticException: / by zero
            at Demo.div(ExceptionDemo.java:5)
            at ExceptionDemo.main(ExceptionDemo.java:15)
    从上面的结果可以分析出,在第5和第15行都出现了异常,这是因为除法的机制,除数不能为0,这时候运行就抛出了异常。



    实例2:出现异常示例2,内存溢出

     1 class Demo
     2 {
     3     public int div(int x,int y)
     4     {
     5         return x/y;
     6     }
     7 }
     8 
     9 
    10 class ExceptionDemo
    11 {
    12     public static void main(String args[])
    13     {
    14         /*Demo d=new Demo();
    15         int x=d.div(4,0);
    16         System.out.println("x="+x);
    17         System.out.println("over");
    18         */
    19         byte[] arr=new byte[1024*1024*1000];
    20     }
    21 }

    运行结果:

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
            at ExceptionDemo.main(ExceptionDemo.java:19)

    java.lang.OutOfMemoryError:代表内存溢出异常

    二、异常的处理:

    对于异常的处理,java提供了特有的语句进行处理

    格式

    try

    { 

      需要被检测的代码; 

    }

    catch

    {

      处理异常的代码;(处理方式)

    }

    finally

    {

      一定会执行的代码;(处理方式)

    }

    实例1:演示try  catch语句

    class Demo
    {
        public int div(int x,int y)
        {
            return x/y;
        }
    }
    
    
    class ExceptionDemo
    {
        public static void main(String args[])
        {
            Demo d=new Demo();
            try
            {
                int x=d.div(4,0);
                System.out.println("x="+x);
            }
            catch(Exception e)
            {
                System.out.println("除数有误");
            }
            
            System.out.println("over");
            
            /*byte[] arr=new byte[1024*1024*1000];*/
        }
    }

    运行结果:

    除数有误

    over

    结果分析:程序在运行时,当执行到除法的语句:return x/y时,就生成了异常的对象 new AritchmeticException(),try语句把这个对象让catch语句的参数捕获

    Exception e =new AritchmeticException();

    运行完catch的处理语句后,问题就被处理完了,结束语句,输出over

    实例2:对捕获到的异常对象进行常见的方法操作(父类Throwable的方法)

              String getMessage();                 //获取异常信息

               toString()                                //返回异常名称:异常信息

              printStackTrace()                      //输出异常名称,异常信息,异常出现的位置

    
    
     1 class Demo
     2 {
     3     public int div(int x,int y)
     4     {
     5         return x/y;
     6     }
     7 }
     8 
     9 
    10 class ExceptionDemo
    11 {
    12     public static void main(String args[])
    13     {
    14         Demo d=new Demo();
    15         try
    16         {
    17             int x=d.div(4,0);
    18             System.out.println("x="+x);
    19         }
    20         catch(Exception e)
    21         {
    22             System.out.println("除数有误");
    23             //获得异常信息
    24             System.out.println(e.getMessage());
    25             //获得异常信息,异常名称
    26             System.out.println(e.toString());
    27             //输出异常名称,异常信息,异常出现的位置
    28             e.printStackTrace();                 
    29         }
    30         
    31         System.out.println("over");
    32         
    33         /*byte[] arr=new byte[1024*1024*1000];*/
    34     }
    35 }
    
    
    
    
    

    运行结果:

    除数有误
    / by zero
    java.lang.ArithmeticException: / by zero           
    java.lang.ArithmeticException: / by zero
            at Demo.div(ExceptionDemo.java:5)
            at ExceptionDemo.main(ExceptionDemo.java:17)
    over

    从运行结果分析,其实jvm默认异常处理机制就是在调用printStackTrace方法。

    实例3:抛出异常的两种处理方式

    1.抛出给jvm虚拟机处理

    2.抛出的异常自己处理

     1 class Demo
     2 {
     3     public int div(int x,int y)throws Exception       /*有可能出现异常的地方抛出异常*/
     4     {
     5         return x/y;
     6     }
     7 }
     8 
     9 
    10 class ExceptionDemo
    11 {
    12     public static void main(String args[])
    13     {
    14         Demo d=new Demo();    
    15         int x=d.div(4,0);
    16         System.out.println("x="+x);        
    17         System.out.println("over");        
    18     }
    19 }

    运行结果:

    ExceptionDemo.java:15: 错误: 未报告的异常错误Exception; 必须对其进行捕获或声明以
    便抛出
            int x=d.div(4,0);
                       ^
    1 个错误

    结果分析:这是因为没有对有可能出现异常进行处理

    处理方式1:不断抛出异常,让jvm虚拟机自己处理

     1 class Demo
     2 {
     3     public int div(int x,int y)throws Exception       /*有可能出现异常的地方抛出异常*/
     4     {
     5         return x/y;
     6     }
     7 }
     8 
     9 
    10 class ExceptionDemo
    11 {
    12     public static void main(String args[])     throws Exception   /*继续抛出异常,给虚拟机*/
    13     {
    14         Demo d=new Demo();    
    15         int x=d.div(4,0);
    16         System.out.println("x="+x);        
    17         System.out.println("over");        
    18     }
    19 }

    处理方式2:自己处理异常

     1 class Demo
     2 {
     3     public int div(int x,int y)throws Exception       /*有可能出现异常的地方抛出异常*/
     4     {
     5         return x/y;
     6     }
     7 }
     8 
     9 
    10 class ExceptionDemo
    11 {
    12     public static void main(String args[])     
    13     {
    14         Demo d=new Demo();
    15         try                                      //自己处理异常
    16         {
    17             int x=d.div(4,0);
    18             System.out.println("x="+x);
    19         }
    20         catch(Exception e)
    21         {
    22             System.out.println("除数有误");
    23             //获得异常信息,异常名称
    24             System.out.println(e.toString());    
    25             System.out.println("over");    
    26         }
    27     }
    28 }

     

    总结:

    在函数上声明异常。便于提高安全性,让调出处进行处理,不处理编译失败。

    实例4:对多异常处理

    1.声明异常时,建议声明更为具体的异常,这样处理得可以更具体

    2.声明几个异常,就对应有几个catch块,不要定义多余的catch快。

      如果有多个catch块中的异常出现继承关系,父类异常catch块放在下面。

     1 class Demo
     2 {
     3     public int div(int x,int y)throws ArithmeticException,ArrayIndexOutOfBoundsException        
     4     {
     5         int arr[]=new int [x];
     6         System.out.println(arr[4]);
     7         return x/y;
     8     }
     9 }
    10 
    11 
    12 class ExceptionDemo
    13 {
    14     public static void main(String args[])     
    15     {
    16         Demo d=new Demo();
    17         try                                      
    18         {
    19             int x=d.div(4,0);
    20             System.out.println("x="+x);
    21         }
    22         catch(ArithmeticException e)                   /*除法法则异常对象接收,第一个执行*/
    23         {
    24             System.out.println("除数有误");
    25             //获得异常信息,异常名称
    26             System.out.println(e.toString());    
    27             System.out.println("over");    
    28         }
    29         catch(ArrayIndexOutOfBoundsException e)        /*数据越界的对象接收,第二个执行*/
    30         {
    31             System.out.println("数组越界了");
    32             //输出异常信息
    33             System.out.println(e.toString());
    34         }
    35         catch(Exception e)                             /*父类Exception接收,最后执行,建议不要写这个,让程序终止*/ /*用到了多态*/
    36         {
    37             System.out.println(e.toString());
    38         }
    39     }
    40 }

    运行结果:

    数组越界了
    java.lang.ArrayIndexOutOfBoundsException: 4

    建议:

    建立在catch处理时,catch中一定要定义具体的处理方式

    不要简单定义一句 e.printStackTrace().

    也不要简单就书写一条输出语句

    因为用户看不懂,最好保存到文件中,定时发给我们开发者去查看。

    实例5:自定义异常

    你们有没有发现,我们正在使用的异常都是java中封装好的

    但在实际开发中,我们的程序中出现的异常,有可能是java没有封装的,

    这时候,就需要自己定义了

    我根据上面的代码,定义除数不能为负数,代码如下

     1 class Demo
     2 {
     3     public int div(int x,int y)throws FuShuException   /*抛出异常*/    
     4     {
     5         if(y<0)
     6         {
     7             throw new FuShuException("分母出现负数了------/bu FuShu",y);   /*自己手动抛出异常的对象*/
     8         }
     9         return x/y;
    10     }
    11 }
    12 class FuShuException extends Exception
    13 {
    14     private int value;
    15     FuShuException(String m,int value)
    16     {
    17         super(m);                                   /*给父类Exception的getMessage方法传递参数*/
    18         this.value=value;
    19     }    
    20     public int getValue()                           /*自定义的方法,返回负数*/
    21     {
    22         return value;
    23     }
    24 }
    25 
    26 class ExceptionDemo
    27 {
    28     public static void main(String args[])     
    29     {
    30         Demo d=new Demo();
    31         try                                                            
    32         {
    33             int x=d.div(4,-3);
    34             System.out.println("x="+x);
    35         }
    36         catch(FuShuException e)                   /*捕获异常对象*/
    37         {
    38             System.out.println(e.getMessage()+e.getValue());
    39         }
    40         System.out.println("over");
    41     }
    42 }

    运行结果:

    分母出现负数了------/bu FuShu-3
    over

    从上面的结果,可以看出



    在本程序中,对于除数是-3,也视为是错误的是无法进行运算的。
    那么就需要对这个问题进行自定义的描述。

    当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。
    要么在内部try catch处理。
    要么在函数上声明让调用者处理。

    一般情况在,函数内出现异常,函数上需要声明。


    发现打印的结果中只有异常的名称,却没有异常的信息。
    因为自定义的异常并未定义信息。

    如何定义异常信息呢?
    因为父类中已经把异常信息的操作都完成了。
    所以子类只要在构造时,将异常信息传递给父类通过super语句。
    那么就可以直接通过getMessage方法获取自定义的异常信息。



    自定义异常必须是自定义类继承Exception。


    继承Exception原因:
    异常体系有一个特点:因为异常类和异常对象都被抛出。
    他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。

    只有这个体系中的类和对象才可以被throws和throw操作。

    throws和throw的区别
    throws使用在函数上。
    throw使用在函数内。

    throws后面跟的异常类。可以跟多个。用逗号隔开。
    throw后跟的是异常对象。

    实例6:Exception中有一个特殊的子类异常RuntimeException 运行时异常

    如果在函数内容抛出该异常,函数上可以不声明,编译一样通过。

    如果函数上声明了该异常,调用者可以不进行处理,编译一样通过

    之所以不用在函数声明,是因为不需要让调用者处理

    当该异常发生,希望程序停止,因为在运行时,出现了无法运行的情况,希望程序停止后

    程序员对该代码进行修改。

     1 class Demo
     2 {
     3     public int div(int x,int y)throws FuShuException     /*抛不抛结果都一样*/
     4     {
     5         if(y<0)
     6         {
     7             throw new FuShuException("分母出现负数了------/bu FuShu",y);   
     8         }
     9         return x/y;
    10     }
    11 }
    12 class FuShuException extends RuntimeException         /*继承RuntimeException*/
    13 {
    14     FuShuException(String m,int value)
    15     {
    16         super(m);                                   
    17         
    18     }    
    19 }
    20 
    21 class ExceptionDemo
    22 {
    23     public static void main(String args[])     
    24     {
    25         Demo d=new Demo();
    26         int x=d.div(4,-3);                            /*运行到这会出现异常,编译没有问题*/
    27         System.out.println("x="+x);
    28         System.out.println("over");
    29     }
    30 }

    运行结果:

    Exception in thread "main" FuShuException: 分母出现负数了------/bu FuShu
            at Demo.div(ExceptionDemo.java:7)
            at ExceptionDemo.main(ExceptionDemo.java:26)

    从上面的结果可以看出:

    自定义异常时:如果该异常的发生,无法在继续进行运算,
    就让自定义异常继承RuntimeException。


    对于异常分两种:
    1,编译时被检测的异常。
        
    2,编译时不被检测的异常(运行时异常。RuntimeException以及其子类)

    我还写了一些关于异常的练习,具体看我的博客,加深对异常的理解。

  • 相关阅读:
    DTOJ #3328. 开箱子(unboxing)
    dtoi4649 光明
    dtoi4539「TJOI / HEOI2016」序列
    dtoi3031 交错和查询 (sum)
    dtoi4375「BJOI2019」删数
    dtoi4266 exchange
    dtoi4680 红黑兔
    dtoi1363 楼房重建 (rebuild)
    dtoi1927 [ONTAK2010]Peaks加强版
    dtoi4538 「TJOI / HEOI2016」排序
  • 原文地址:https://www.cnblogs.com/liangqiyuan/p/5576156.html
Copyright © 2020-2023  润新知