黑马程序员--Java基础之异常Exception

时间:2021-07-31 12:56:33

黑马程序员--Java基础之异常Exception

------------------ android培训java培训、期待与您交流! ---------------------

一、异常概述

1、异常是什么:是对问题的描述,将问题进行对象的封装。

2、异常体系:Throwable:

|---Error,严重的问题,对于Error一般不编写针对性的代码对其进行处理。

|---Exception,非严重的问题,可以针对性处理。

|---RunTimeException;

异常体系的特点:异常体系中的所有类及对象都具有可抛性。即都可以被throws和throw关键字所操作。只有异常体系具备这个特点。

二、异常的两种处理方式

1、第一种try()catch(){}finally{}处理

try{

需要被检测的代码;

}catch(异常类  变量){//这里的变量接受try代码中检测到的异常如:Exception(父类) e = new 异常类();

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

}finally{

一定会执行语句;

}

finally语句块中存放的是一定会被执行的语句,通常用于关闭资源。finally有一种情况是执行不到的:前面有System.exit(0);即系统退出。

e.getMessage();//异常信息

e.toString();//异常名称 : 异常信息

e.printStackTrace();//打印追踪信息。异常名称+异常信息+异常出现的位置。jvm默认的异常处理机制,就是在调用printStackTrace方法,打印异常的堆栈跟踪信息。

特殊:method(){

       try{throw newException();}catch(Exception e){}//这样编译也是可以通过的,因为这个抛出的异常立马在内部catch中解决掉了。

             }

2、第二种处理方式,将异常抛出throws和throw,以及二者区别。

throws用于函数上,用于抛出异常类,可以同时抛出多个,用逗号分隔。

        throw用于函数内部,抛出异常对象:thrownew 。。。();

   当函数内有throw抛出异常对象,并且trycatch中没有处理此异常,那么必须在函数上声明一下,否则编译失败。(RuntimeException及其子类除外)。

3、多异常的处理。

       多异常抛出,如:intdiv(int a,int b) throws Arit....Exception,Ari...Exception

这时需要有两个catch(具体的异常声明){},或者一个catch(Exception e){}但是这样并不是针对性的处理,建议使用更针对性的处理。

对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最后面。否则编译错误!建议在进行catch处理时,一定要定义具体处理方式。正规使用异常日志。

4、运行时异常RuntimeException,特殊的Exception子类。

异常分为两种

*编译时被检测异常:编译时如果没有处理(throws或者try catch),编译失败。该异常被标识,代表可以被处理。

*运行时异常:编译时不检测,所以在编译时不需要处理,编译器不检查。该异常的发生,建议不处理让程序停止,需要对代码进行修正。

如果是RuntimeException的子类,在函数内抛出异常,函数上不声明,编译一样通过。也不需要让调用者处理,当该异常发生,希望程序停止,因为在运行时出现了无法继续运算的情况,希望停止程序后对代码进行修正。自定义异常时,如果该异常的发生无法再继续进行运算,就让自定义异常继承RuntimeException。

5、当捕获到的异常本功能处理不了时,可以继续在catch中抛出;如果该异常处理不了且不属于该功能出现的异常,可以将异常转换后,再抛出和该功能相关的异常; 或者异常可以处理,但需要将异常产生的和本功能先关的问题提供出去,让调用者知道并处理。也可以将捕获异常处理后,转换成新的异常。比如汇款例子。

 

三、自定义异常

有些项目中出现的特有问题并未被java所描述并封装对象,所以对于这些特有的问题可以按照java的对问题封装的思想,进行自定义的异常封装。

1、自定义异常,需要手动抛出:if() throw new FuShuException;//通过throw关键字抛出

2、自定义异常必须是自定义类继承Exception。因为这样才具备可抛性。

3、自定义异常练习

需求:毕老师用电脑上课

问题:电脑蓝屏,电脑冒烟

问题描述,封装成对象。

讲师问题:课时无法继续

代码示例:

/*
需求:毕老师用电脑上课
问题:电脑蓝屏、电脑冒烟
       老师课时计划无法完成
对问题进行描述封装成java对象
*/
classLanPingException extends Exception{
       LanPingException(String msg){
              super(msg);
       }
}
 
class MaoYanExceptionextends Exception{
       MaoYanException(String msg){
              super(msg);
       }
}
 
classNoPlanException extends Exception
{
       NoPlanException(String msg)
       {
              super(msg);
       }
}
 
class Computer{
       private int state = 2;
       Computer(){}
       public void run() throws LanPingException,MaoYanException
       {     if(state== 2)
                     throw newLanPingException("电脑蓝屏了,可以解决的");
              if(state == 3)
                     throw newMaoYanException("电脑冒烟了 没办法了");
              System.out.println("theComputer is running...");
       }
      
       public void reset(){
              System.out.println("电脑重启了,OK");
              state = 1;
       }
       public int getState(){
              return state;
       }
}
 
class Teacher{
       private String name;
       private Computer c;
       Teacher(){}
       Teacher(String name){
              this.name = name;
              this.c = new Computer();
       }
      
       public void Jiangke()throws NoPlanException
       {
              try
              {
                     c.run();
              }
              catch(LanPingException e)
              {
                     System.out.println(e.getMessage());
                     c.reset();
                           
                     int x = c.getState();
                     System.out.println(x);
                     //下面如果还要运行run()方法必须还要处理一下,也就是需要try catch一下
                     //try
                     //{c.run();
                     //}catch(..){...}
              }
              catch(MaoYanException e) //throwsNoPlanException
              {
                     System.out.println(e.getMessage());
                     throw newNoPlanException("课时计划完不成了,放假吧");   
              }
              System.out.println("theTeacher is working..");
       }
      
       public void test()
       {
              System.out.println("做点练习吧");
       }
}
 
class Test9_12{
       public static void main(String[] args){
              Teacher t =new Teacher("老毕");
              try
              {
                    
                     t.Jiangke();
              }
              catch(NoPlanException e)
              {
                     t.test();
                     System.out.println(e.getMessage());
              }
             
             
       }
}


四、覆盖时的异常特点

1、子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者异常的子类(如使用中用到多态。。)

2、如果子类中真的还有其他异常,这个异常一定要在内部catch中解决掉,不能再抛。

3、如果父类中抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子类。

4、如果父类或者接口的方法中没有异常抛出,子类覆盖时,也不可以抛出异常。

       如果子类方法发生了异常,就必须在catch中处理掉,绝对不能抛出。

 

五、异常的好处

1、将问题进行封装。

2、将正常流程代码和问题处理代码分离,方便阅读。