先从 java 异常基础 入手,在学习了这些基本知识后,该思考怎么活学活用,异常使用时的注意点,怎么用好异常这些问题了,可以研究下
Effective Java中异常一章,J2EE项目异常处理。
异常和错误的区别
在程序的运行过程中,会出现某些特殊情况。其中可以处理的叫做
异常(java.lang.Exception),不能处理的严重问题叫错误(java.lang.Error)
java异常机制
1 当执行到产生异常的代码时,由JVM或程序员抛出异常对象
2 寻找异常处理的代码(try/catch),如果有,处理完毕
3 如果没有找到,继续上抛(抛到上一层),继续寻找
4 如果到main()方法中还没有处理,异常会中断代码的执行
5 每抛出一层,异常会中断当前层的代码
Java异常体系结构
java提供了三种可抛出结构(throwable):检测异常、非检测异常和Error。
-class Error
-class Exception
下面是check异常
-IOException
-SQLException
-TimeoutExcepton
-ClassNotFoundException
-CloneNotSupportedException
-DataFormatException
…………………..
下面是uncheck异常
-RuntimeException
何时使用异常?
异常应该只用于异常的情况下,而不应该用于正常的控制流。
典型例子是遍历数组,怎么处理数组越界问题?怎么在数组不越界下正常操作?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条