黑马程序员——Java基础---异常

12/12/2015来源:Java教程人气:1172

-----------android培训java培训、java学习型技术博客、期待与您交流!------------ 

 

1:异常的概念

  异常是java程序运行的过程中出现的一些问题。将异常问题封装为对象。(又一次体现了万物皆对象的思想)

2Throwable体系

  问题体系主要由Throwable、Error、Exception、RuntimeException(运行时异常)。如图1所示 

图 1

          

  Error是一些已经超出程序本身处理能力的问题,如内存溢出、虚拟机错误等等。这类问题一般与硬件有关,与程序本身无关,通常由系统进行处理,程序本身无法捕获和处理。

  Exception是我们在编写程序时无法预料的异常,如调用者传取参数异常、证书异常、实例化异常等等。为了保证java的健壮性,编写程序时需要对这种问题进行抓取、捕获、处理等。

3:Throwable体系的特点

         Throwable体系的所以类(Throwable、其子类以及自定义异常类)及建立的对象都具备可抛性。即关键字Throw可以操作抛出类,throws可以操作对象。只有异常体系的类及对象具有可抛性。

4:异常的两种类型

         异常两种类型:RuntimeException(运行时异常)、非RuntimeException(编译时异常)。

4.1RuntimeException

         RuntimeException顾名思义就是这个异常在编译期间不会发生,只有在jvm运行时才会发生。这样做是因为发生这样的异常时不需要编译者进行处理的,而是希望程序停止,让专业人员对代码进行改正。例如(NullPointerException)空指针异常。

1 class Demo{
2     public static  void main(String[] args){
3         Demo d = new Demo();
4         int x = d.divise(4,0);
5     }
6     int divise(int a,int b){
7     return a/b;
8 }
9 }

  这个程序在编译期间是检测不出来错误的,因为没有任何语法错误,可是在运行期间,就会报错。这就需要我们返回去对代码进行修改

4.2:非RuntimeException

         非RuntimeException称作编译时异常。该异常必须要进行处理。要么是在函数内部进行捕获(try、catch);要么就是抛出异常对象(throw异常对象),并且在函数声明上强调(throws 异常类)。

5:异常处理语句

         异常处理语句需要用到三个关键字:try、catch、finally。

5.1:三种结合方式

 

  这里需要注意的是finally中一般添加的是必须要执行的语句,及时发生异常,也会执行,比如资源关闭。只有一种情况finally中的语句才不会杯执行,那就是System.exit(0)。

6:自定义异常类

  在我们做项目的时候,往往遇到一些特殊的异常,或者我们不满意java自带的异常描述,那我们就需要自己定义异常类。牢记-------自己定义的异常类,继承自Exception和RumtimeException。这样自己的异常类就具有可抛性,而且可以使用异常类中的一些共性方法。如

1 class MyException extends Exception{ //或者是RuntimeException
2     MyException(String str){    //字符串为自定义异常的专属信息
3         super(str);//利用Exception中的构造方法构造带有特有信息的异常
4     }
5 }

  将特殊的异常包装起来,一是遵从了java的面相对象思想;二是可以将正常的运行代码和和问题处理代码分离,有利于阅读。

7:异常的处理原则

  1:对于异常,可以捕获(try、catch),也可以向外抛(throws)。

  2:调用到异常功能的语句,抛出(throws)几个异常,就需要捕获几个异常。那这就注定了一个try,后面可以跟若干个catch语句。但有一点需要牢记的就是,捕获异常时,异常子类往前写,异常父类往后写。这就像我们去补鱼时,一定是网眼小的网在前面,网眼大的网在后面。如果将异常父类放在前面,子类放后面,那么一定是后面的异常不会执行。

  3:当catch中捕获到的异常无法处理时,也可以继续向外面抛出。例如

1 try{    
2     throw new AException();
3 }
4 catch(AException a){
5     throw e;
6 }

  4:如果捕获到的异常处理不了,但与本功能无关,就可以将异常转化为与本功能相关的功能异常,然后在抛出。

  5:如果捕获的异常可以处理,当需要将异常所产生的和本功能相关的问题提供出去,以便让调用者知道,并处理。

1 try{    
2     throw new TransferAccountsException();
3 }
4 catch(TransferAccountsException a){
5     转账失败;//将本异常产生的,与本问题相关的问题呈现出来
6     异常处理语句;//
7 }

8:异常的注意事项 

  1:子类抛出的异常必须是父类的异常类的子类或者子集。既父类抛出一个IOException,子类只能发IOException或者及其子类。如果父类跑出三个异常类,子类也最多只能抛出三个,且这三个一定要是父类的的异常或者父类异常的子类。

  2:如果父类没有抛出异常,那么子类覆盖之后出现异常的话,子类就只能捕获处理,而不能往出抛。

9:异常处理的流程

  1:遇到错误,抛出一个异常对象(如果写程序的时候已经写进去了,那就抛你写的异常,如果什么都没写,系统就默认抛异常对象)方法立即结束,并不会返回一个值。

  2:调用该方法的程序也不会继续执行下去,而是搜索一个可以处理该异常的异常处理器,并执行其中的代码。如下程序代码的执行顺序:first-second-third。

 

 1 class Demo{
 2     public static  void main(String[] args){
 3         Demo d = new Demo();
 4         int x = d.divise(4,0);//third:这句话也结束,同时去搜索异常处理器,并执行其中的代码。在这里就是执行异常对象的toString();
 5         
 6         System.out.PRintln("会不会打印这句话");
 7     }
 8     int divise(int a,int b){
 9         if(b==0)//first:出现错误
10             throw new ArithmeticException("除011了");//second:抛出一个对象,同时方法结束,无返回值。
11     return a/b;
12     }
13 }

10:总结

  1:如果在方法中抛出了编译时异常对象,则在方法声明中就必须体现(throws);而在方法中抛出了运行时异常(RumtimeException),就不需要在方法声明中体现。

  2:对于自己的自定义异常类如何判断其应该继承自Exception还是RuntimeException。一般看这个异常会不会影响后续的程序运行,如果会影响,让自定义异常类继承自RuntimeException;如果不会影响的话,那就使自定义异常类继承Exception。