【Core JAVA】异常


  先从 java 异常基础 入手,在学习了这些基本知识后,该思考怎么活学活用,异常使用时的注意点,怎么用好异常这些问题了,可以研究下

Effective Java中异常一章J2EE项目异常处理


异常和错误的区别

在程序的运行过程中,会出现某些特殊情况。其中可以处理的叫做

异常(java.lang.Exception),不能处理的严重问题叫错误(java.lang.Error)



java异常机制

1 当执行到产生异常的代码时,由JVM或程序员抛出异常对象

2 寻找异常处理的代码(try/catch),如果有,处理完毕

3 如果没有找到,继续上抛(抛到上一层),继续寻找

4 如果到main()方法中还没有处理,异常会中断代码的执行

5 每抛出一层,异常会中断当前层的代码


Java异常体系结构

java提供了三种可抛出结构(throwable):检测异常、非检测异常和Error。

【Core JAVA】异常
 -class Throwable

         -class Error

         -class Exception

                   下面是check异常

                   -IOException

                   -SQLException

                   -TimeoutExcepton

                   -ClassNotFoundException

                   -CloneNotSupportedException

                   -DataFormatException

                   …………………..

                   下面是uncheck异常

          -RuntimeException

          -IllegalStateException



何时使用异常?

异常应该只用于异常的情况下,而不应该用于正常的控制流。

典型例子是遍历数组,怎么处理数组越界问题?怎么在数组不越界下正常操作?Iterator提供了状态测试方法hasNext()及取值方法next(),next是个状态相关方法,对于Iterator的遍历采取的策略是


for(Iterator<Foo> it = collection.iterator(); it.hasNext(); ){ Foo foo = it.next(); ... }

 对于正常的操作流需要避免使用异常,通常有两种做法:

1.针对“状态相关操作” 提供 “状态测试代码”  2.“可识别的返回值”

做法1,就要考虑是否存在并发访问时的线程安全问题(竞争条件),“状态相关操作” 和 “状态测试代码”操作的对象是否是跨线程的共享变量,其状态是否可改变,是否需要在访问该变量的时候使用同步。

做法2要考虑是当对象处于不适当状态中返回的可识别值是否是合法的值,如null、-1等。


检测异常与非检测异常的比较与选择

      Runtime Exception(运行时异常,非检测异常 unchecked exception) --- 这类异常是程序员没有进行必要的检查,由于疏忽和错误而产生的。通常使用if判断处理。属于虚拟机内部的异常。

      非Runtime Exception(编译时异常,检测异常 checked exception)  -- 常常用try/catch处理。


【理解】:首先异常通常分为两类,Runtime Exception和非Runtime Exception,对于Runtime Exception,中文名为非检测异常,就是程序员没有进行相应的检测而产生的异常,比如,除法中除数为0,某个变量为null,数组越界等等。检测的方法就是在操作前通过if( )进行检测。而检测异常是通过try/catch由编译器来进行检测,而Runtime Exception在编译时是不能检测的,只有运行后才能检测到。

另外在程序中,自定义异常类时public Class xxException extends Exception,该异常是检测异常,

Public Class xxException extends RuntimeException,该异常是非检测异常。

【如何选择】

如果期望调用者能够适当地恢复,对于可恢复情况应该使用检测异常。

对于编程错误或者前提违例(API使用者没有遵守API使用的规范),应该使用非检测异常。

即:如果正确地使用API并不能阻止异常条件的产生,并且一旦产生异常,使用API的程序可以立即采取有用动作,这样使用检测异常时合适的,否则使用非检测异常。

在进行API设计时,我们不要忽略了,异常也是个完全意义上的对象,可以在上面定义任意的方法,这些方法主要用于为捕获异常的代码提供额外的信息,特别是关于引发这个异常条件的信息。对于检测异常提供这样的辅助方法尤为重要,调用者可以获得一些有助于恢复的信息。例如:一个电话用户因为没有在账户中存入足够的钱,而使在一个收费电话上呼叫失败,于是抛出一个检测异常。这个异常应该提供一个访问方法,以便允许客户查询所缺的金额。


5种常见的非检测异常RuntimeException

1. java.lang.NullPointerException

2. java.lang.ArithmeticException  算数异常(如0作除数,负数被开方)

3. java.lang.ArrayIndexoutofBoundsException

4. java.lang.NumberFormatException 数字格式异常    

如:“abc” --> int

解决办法是 int的正则判断

String intReg = "^-?[0-9]$";

if(str2.matches(intReg)){

int in2 = Integer.parseInt(str2);

}

5. java.lang.ClassCastException  类型转换异常

如:Object obj = 3;

String str = (String)obj;

解决方法是

Object obj = 3;

If(obj  instanceof  String)

   String str = (String)obj;


6. java.lang.IllegalArgumentException

抛出的异常表明向方法传递了一个不合法或不正确的参数

7. java.lang.IllegalStateException

因为接收对象的状态而使调用非法,例如:如果在某个对象被正确初始化之前,调用者就企图使用这个对象,就会抛出该异常。

在http://www.cs.duke.edu/csed/ap/subset/doc/ap/java/lang/IllegalStateException.html对该异常有这样的说明

In the AP subset, an IllegalStateException might be thrown if a class invariant isn't satisfied(变量不能让人满意). For example it might be appropriate to throw this exception if a class representing a month in a calendar year is constructed with the integer 15 when only integer values in the range 1-12 represent valid months.


注意:确保抛出异常的条件与该异常的文档中描述的条件一致。

 

后续:

1.《Effective java》第61条

 

 

 

 

 

你可能感兴趣的:(java)