zoukankan      html  css  js  c++  java
  • day09(下)_异常(上)

    异常概述:

    /*
     异常: 就是程序在运行时出现不正常情况
     异常由来: 问题也是现实生活中一个具体的事物,
               也可以通过java类的形式进行描述.
               并封装成对象.其实就是java对不正常情况
               进行描述后的对象体现
    
    对于问题的划分:
        两种:一种是严重的问题,一种是非严重的问题
    严重的:java通过Error类进行描述
         对于Error一般不编写针对性的代码对其进行处理
    非严重:java通过Exception类进行描述
         对于Exception可以使用针对性的处理方式进行处理
    
    
    无论Error或者Exception都具有一些共性内容
    比如: 不正常情况的信息,引发原因等.
    
    Error类和Exception类向上抽取-->Throwable类(可查Java API文档)                                                          
                                 (可抛出/异常)
    java 提供特有的语句进行处理
    
    try
    {
    
       需要被检测的代码({ }之间的代码抛出异常,均可用下面catch接收)
    }
    catch(异常类 变量)
    {
      处理异常的代码;(处理方式)
    
    }
    finally
    {
    
      一定会执行的语句;
    }
    3.对捕获到的异常对象进行常见方法操作
      String getMessage():返回throwable的详细消息的字符串
    */
    //以 除零 为例
    class Arithmetic
    {
    
     public int div(int a,int b)
     {
      return a/b;
    //
    产生一个JVM识别的ArithmeticException问题
    //把该问题封装成一个new ArithmeticException(); //
    然后把该问题抛给调用该功能(div)的调用者}
    
    }
    
     
    class ExceptionDemo1
    {
        public static void main(String[] args) 
        {
         try//检测问题
            //不写try的话,主函数(被JVM调用)没办法处理该问题-->给了JVM-->JVM进行默认处理-->调用默认异常处理机制-->停止程序
            
           //try检测到该问题对象把问题对象丢给catch(捕获)
         {
           int x= new Arithmetic().div(4,0);
           System.out.println("x="+x);//上面的代码已发生问题将不再执行,无任何意义
         }
         catch (java.lang.Exception e)//Exception e=new ArithmeticException(); 
        { 
           System.out.println("除零了");
           System.out.println(“e.getMessage()\t”+e.getMessage());// / by zero
           System.out.println(“e.toString()\t”+e.toString());//异常名称:异常信息
    
           e.printStackTrace();//异常名称,异常信息,异常出现的位置
         }                      //其实JVM默认的异常处理机制,就是在调用printStatckTrace()方法
                                //打印异常堆栈的跟踪信息
         //以上问题处理完try...catch
        System.out.println("over");
        }
    }
    /*
    关于命名问题:
    (运行图二)
    如果我的源文件名用了关键字Exception.java
    命名这里如果不加java.lang将无法通过编译  
    在src.zip的lang文件夹下也有一个Exception.java
    JVM并没有编译lang下的Exception.java因此不能使用Exception类
    因此加上java.lang,但是强烈不建议源文件名用关键字命名!!!!
    */

    图一:

    ExceptionDemoLate

    图二:

    Exception

    2.为什么要在函数上声明异常?

    /*
    为什么要在在函数上声明异常??
        当功能被封装时,只能看见函数声明,根本不知道使用功能会不会发生问题.
        因此编写功能的人,在功能后加了个标识(trows+异常类),在功能上通过throws的关键字声明了该功能有可能会出现问题 
        
        便于提高安全性,让调用者进行处理,不处理则编译失败
    */
    class Arithmetic 
    {
        public int div(int a,int b) throws Exception//把该问题抛给调用该功能(div)的调用者 
        {
         return a/b;
        }
    }
    class ExceptionDemo1
    {
        public static void main(String[] args) throws Exception//主函数也不处理,把问题抛给了JVM
        {
         int x=new Arithmetic().div(1,0);
         System.out.println("x="+x);
         System.out.println("over");
        
        }
    }
    ExceptionDemo

    3.多异常处理:

    /*
    对多(个 )异常处理
        1.声明异常时,建议声明更为具体的异常.这样处理的更为具体(可以抛该异常的直接或间接父类异常)
    
        2.对方声明几个异常,就对应有几个catch块
          
          如果多个catch块中的异常出现继承关系,
          父类异常catch块放在最下面.因为父类catch可以处理子类异常,接收子类的catch没用
    
    建议在进行catch处理时,catch中一定要定义具体的处理方式.
    
    不要简单定义一句 e.printStackTrace()
    也不要简单的就书写一条输出语句
    因为用户看不懂(没任何用处),一般会把问题(信息)用一个文件记录下来(异常日志文件),记录着程序
    的运行状况,便于管理员管理和解决.
    
    
    
    
    如果出现未知异常,不要用catch(Exception e)处理
    这样做就不能发现异常原因
    */
    class Arithmetic
    {
      public int div(int a,int b) throws ArithmeticException,ArrayIndexOutOfBoundsException
                                  //算术异常,数组越界异常
                                  //throws Exception  抛出的异常不具体 
    //因为在功能上通过throws的关键字声明了该功能有可能会出现问题 
      {  
       int[] arr=new int[a];
       System.out.println(arr[4]);
       return a/b;
      }
    }
    class ExceptionDemo2
    {
     public static void main(String[] args) //throws Exception//如果调用者不处理该问题,主函数把问题抛给JVM,JVM进行默认处理
        {                                   //一般都是检测问题,然后捕捉进行处理 try..catch
            try
            {
            int x=new Arithmetic().div(4,0);
            System.out.println("x="+x);    
            }
            /*
            catch(Exception e)//这两个异常都能处理,因为多态
            {                 //但是不建议这样写-->处理没有针对性
              System.out.println(e.toString());
            
            }
            //不能与以下两个catch共存
            //因为这个catch块已处理异常,下面两个没用
            */
    catch (ArithmeticException e)//针对算术异常处理
            {
                  System.out.println(e.toString()+"\n被零除了");
            }
            catch(ArrayIndexOutOfBoundsException e)//针对数组越界异常处理
            {
                  System.out.println(e.toString()+"\n数组越界");
            }
            
            System.out.println("over");
        }
    }
    /*
    以上两个异常不会同时发生,
    这是因为当角标一越界
    System.out.println(arr[4]);
    发生异常,函数结束-->抛出数组越界异常
    */

    ArrayIndex 

    4.自定义异常

    /*
    为什么要自定义异常???
         因为项目中会出现特有的问题,
        而这些问题并未被java所描述并封装对象
        所以对于这些特有的问题可以按照java的对问题封装的思想.
        将特有的问题.进行自定义的异常封装.
    
    自定义异常:
     
    需求: 在本程序中,对于除数是-1,也视为是错误的是无法进行运算的.
    那么就需要对这个问题进行自定义的描述
    
    当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作.
        ①要么在内部try..catch处理.
        ②要么在函数上声明让调用者处理.
        一般情况下,函数内出现异常,函数上需要声明
    
    
    自定义异常:
        必须是自定义类继承Exception
        也可以继承Throwable,Throwable下已有一个Exception体系,因此继承了Exception
    
    继承Exception原因:
        异常体系有一个特点:因为异常类(throws)和异常对象(throw)都被抛出
        因为它们都具备可抛性.这个可抛性是Throwable这个体系中独有的特点.
    
    只有这个体系中的类和对象才可以被throws和throw操作
    例如:
    class Person
    {
     
    }
    class Demo
    { 
        public void method() throws Person//错误,Person不可抛
      {
      
      }
    }
    */
    class NegativeException extends Exception
    {
      
      private int value;//显示出该负数
      /*
      ①
      private String mes;
      public NegativeException(String mes)
      {
       this.mes=mes;
      
      }
      public String getMessage()//复写父类中的方法
      {
        return mes;
      }
      */
     
      
      /*
      由于Throwable中有构造函数
      public Throwabel(String message)
      因此有了以下代码:
      */
    
      //把①简化
      //继承关系:Object<-Throwable<-Exception<-NegativeException
      
     public NegativeException(String mes,int value)
      {
        super(mes);      //首先执行Object构造函数初始化—>Throwable构造函数初始化-->接着Exception的-->最后是NegativeException
                         //在下面toString()中会调用从父类继承的getMessage()方法
                           //也就是说:子类内容通过父类初始化
    
       this.value=value; 
      }
      public int getValue()
      {
        return value;
      }
    } 
    //以上类的目的为了创建对象
     class Arithmetic
    {
     
     public int div(int a,int b) throws NegativeException//①要么在内部try..catch处理.
                                                         //要么在函数上声明让调用者处理.
     {
       if(b<0)
         throw new NegativeException("出现了除数是负数",b);//由于自定义异常JVM不能识别,因此通过手动抛出
                                                        //手动通过throw抛出一个自定义异常对象
      
      return a/b;
     }
    
    }
    
     
    class CustomException
    {
        
        public static void main(String[] args) //throws NegativeException
                                               //如果抛给JVM,JVM会报Exception in thread "main" NegativeException..
        {  
          try
          {
            int x= new Arithmetic().div(4,-10);
           System.out.println("x="+x);
          }
          catch(NegativeException e)
          {
              System.out.println(e.toString()+e.getValue());//e.toString()只有异常名称,却没有异常的信息(当NegativeException
                                                                           类中未定义内容时)
          }                                                  //因为系统内部自定义的异常并未定义信息
                                                                     //toString()方法内会调用子类复写的getMessage();   
             
             
          System.out.println("over");      
        }
         
    }

    CustomException4

    5.特殊的异常子类RuntimeException

    /*
    Exception中有一个特殊的 子类异常RuntimeException体系(运行时异常).
    
        如果在函数内容抛出异常,函数上可以不用声明,编译一样通过
    
        如果在函数上声明了该异常.调用者可以不用进行处理(try..catch/throws).编译一样通过.
    
        之所以不用在函数声明,是因为不需要让调用者处理.
        当该异常发生,希望程序停止,不再向下执行.因为在运行时,
        出现了,无法继续运算的情况,希望停止程序后,让使用者对代码进行修正.
    
    自定义异常时:
        如果该异常的发生,无法在继续进行运算(无法处理),
        就让自定义异常继承RuntimeException
        反之,有些可以处理的异常,就在函数上标识(声明)
        进行处理
    对于异常分两种:
         1.编译时被检测的异常
            javac.exe编译时,检测如果在类的方法中抛出非RuntimeException
            或非其子类(例如Exception等),视为可处理的异常
         2.编译时不被检测的异常(运行时异常.RuntimeException及其子类)
            目的让程序停下来
    
    因此在自定义问题时:
      考虑该问题发生时能否处理,不能处理-->继承RuntimeException-->停止程序-->修正代码
      能处理->处理完程序可以继续运行-->继承Exception
    
    */
    class Arithmetic 
    {
        public int div(int a,int b) //throws ArithmeticException//注意在这我不声明,也可以通过编译
        {                         
         if(b==0)
          throw new ArithmeticException("被零除了");//注意在这里抛出了一个异常对象
         return a/b;
        }
    }
    class ExceptionDemo
    {
        public static void main(String[] args) //throws ArithmeticException 
        {
         
          int x=new Arithmetic().div(1,0);
    
           System.out.println("x="+x);
         
         
             System.out.println("over");
         
        }
    }
    
    //例二
    class Person
    {
     public void checkName(String name)
     {
       //if(name.equals("lisi"))//由于name值为null,不能调用Equals
         if("lisi".equals(name))//修正或if(name!=null&&name.equals("lisi"))
         System.out.println("YES");
       else
         System.out.println("NO");
     }
     
    }
    class Demo
    {
     public static void main(String[] args)
     {
       new Person().checkName(null);
     }
    
    }
    RuntimeExceptionDemo

    异常练习:

    /*
    老师用电脑上课
    
    开始思考上课中出现的问题:(增强代码健壮性)
      --> 电脑蓝屏
          电脑冒烟
      -->对对象描述,封装成对象
    
    注意:
        当冒烟发生后,会出现讲课进度无法继续(连锁问题)
        这时候就出现了讲师的问题,课时计划无法完成
    */
    //蓝屏异常类
    class BlueScreenException extends Exception//蓝屏视为可解决问题
    {
     public BlueScreenException(String message)
     {
      super(message);
     }
    }
    //冒烟异常类
    class BrokenException extends Exception
    {                             
      public BrokenException(String message)
      {
       super(message);
      }
                        
    }
    //计划无法进行
    class NoPlanException extends Exception
    {                             
      public NoPlanException(String message)
      {
       super(message);
      }
                        
    }
    
    
    class Pc
    {
      private int state=3;//1代表正常
      public void run() throws BlueScreenException,BrokenException //电脑运行时发生异常
      {
        if(state==2)
            throw new BlueScreenException("蓝屏");
        else
          if(state==3)
            throw new BrokenException("冒烟");
       System.out.println("电脑启动");
      }
      public void reset()
      {
       System.out.println("电脑重启");
       state=1;//回到正常状态
       
      }
    
    } 
    
    class Teacher
    {
      private String name;
      private Pc p;
      public Teacher(String name)
      {
       this.name=name;
       p=new Pc();
      }
      public void teach() throws NoPlanException
      {
        try
        {
          p.run();
        }
        catch (BlueScreenException e)//处理蓝屏问题
        {
             System.out.println(e.toString());
             p.reset();
        
        }
        
        
        catch(BrokenException e)//接收了 冒烟问题 对象
        {                       //但抛出 无法上课 对象
                                           
          test();
          throw new NoPlanException("无法讲课\n"+e.getMessage());//处理不了冒烟,因此抛出无法上课,符合实际
                                                                         //getMessage()获得原因(为什么不能上课?) 
    
    
    //throw下面不能有语句                               
    //因为根本执行不到-->已抛出,该函数结束-->类似return
        }
        
        
        
        System.out.println("开始讲课");
      }
       public void test()
        {
          System.out.println("练习");//做练习吧
        
        }
    }
    
    class ExceptionTest
    {
        public static void main(String[] args)
        {
         try
         {
             new Teacher("zhang").teach();
         }
         catch (NoPlanException e)
         {
            
          System.out.println(e.toString()+"\n换老师或放假");
    
         }
         
        }
    
    }
    /*
    最后注意:
    throws 和 throw 的区别
    1.位置
    throws使用在函数上
    throw使用在函数内
    2.
    throws后面跟的异常类.可以跟多个以","隔开
    throw后跟的是异常对象(异常类的实例) 
    
    */
    ExceptionTest
  • 相关阅读:
    k8s podpreset 参数注入
    python pipenv 包管理
    使用火狐浏览器访问双向认证的k8s api
    k8s api
    常用的排序算法的时间复杂度和空间复杂度
    flask 启动
    Redis系列-第四篇持久化与事务
    Redis系列-第五篇分布式锁与主从复制
    Redis系列-第六篇哨兵模式
    Docker系列-第一篇Docker简介
  • 原文地址:https://www.cnblogs.com/yiqiu2324/p/2950841.html
Copyright © 2011-2022 走看看