码工魄之JAVA异常处理

码工魄之JAVA异常处理
作者:臭豆腐[trydofor.com]
日期:2009-12-16
授权:署名-非商业-保持一致 1.0 协议
声明:拷贝、分发、呈现和表演本作品,请保留以上全部信息。

 

文档目录
1. 异常作用
如果把程序比作一棵树,那么,根系是需求,正常逻辑是主干,异常处理就是枝叶。
枝叶健康得当便有更多机会捕捉阳光雨露,歪斜则易断枝,过大还招风呢 ^_^)
因此,异常处理的好坏,恰当与否,都反映和影响着程序的健康状态与生命力。

JAVA异常有三大类,关系如下:[ST]
java.lang.Object
 |-java.lang.Throwable
    |-java.lang.Error
    |-java.lang.Exception
       |-java.lang.RuntimeException

第一类,是受检异常(checked exception)。
用来提示用户注意和适当的处理,是可预期的和修复的。

第二类,是错误(error),由java.lang.Error及其子类组成。
用来表示程序外部错误,一般不可预期和修复,比如硬件资源。

第三类,是运行时异常(runtime exception),
由java.lang.RuntimeException及其子类组成。
用来表示程序内部错误,一般不可预期和修复,比如程序bug。

2. 大师总结
“Effective Java 第2版”的第九章,专门讲了异常,提到的经验有。[EJ]
  • 第57条:只针对异常的情况才使用异常。
  • 第58条:对可恢复的情况使用受检异常,对编程错误使用运行时异常。
  • 第59条:避免不必要地使用受检异常。
  • 第60条:优先使用标准的异常。
  • 第61条:抛出与抽象相对应的异常。
  • 第62条:每个方法抛出的异常都要有文档。
  • 第63条:在细节消息中包含能捕捉的失败的信息。
  • 第64条:努力使失败保持原子性。
  • 第65条:不要忽略异常。

其中,
第60条指示我们,使用以下常用异常:
  • IllegalArgumentException    参数不合适
  • IllegalStateException       对象状态不合适
  • NullPointerException        禁止null
  • IndexOutOfBoundsException   下标越界
  • ConcurrentModificationException  并发修改
  • UnsupportedOperationException    操作为实现

第61条提到了异常链(exception chaining),经常用到的方法有:
  • Throwable getCause()
  • Throwable initCause(Throwable)
  • Throwable(String, Throwable)
  • Throwable(Throwable)
  • Throwable getStackTrace()
  • Throwable setStackTrace(StackTraceElement[])

3. 常用异常
对jdk1.6.0_16和spring-framework-3.0.0.RELEASE-with-docs.zip的源代码中使用
的异常进行了粗略的统计和排序,以下是过程和结果,也反映了第60条经验。

<tty> 异常的统计过程 
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
pwd
/home/trydofor/java
mkdir java6-src/
cd java6-src/
unzip ../src.zip
cd ..
unzip spring-framework-3.0.0.RELEASE-with-docs.zip
mv spring3-src/spring-framework-3.0.0.RELEASE spring3-src
ll
drwxrwxr-x  2 trydofor trydofor     4096 Dec 19 09:22 java6-src
drwxrwxr-x  2 trydofor trydofor     4096 Dec 19 09:23 spring3-src
-rw-rw-r--  1 trydofor trydofor 46699488 Dec 18 09:07 
                 spring-framework-3.0.0.RELEASE-with-docs.zip
-rw-rw-r--  1 trydofor trydofor 19641221 Jul 31 16:30 src.zip
find java6-src -name '*.java' |wc -l
7196
find spring3-src/projects/ -name '*.java'|wc -l
4093
#spring3-src/projects/org.springframework.expression/src/main/java/org/
#springframework/expression/common/TemplateAwareExpressionParser.java
#这个类是Mac下编写的,需要把 \r换成 \n 才能正确处理,否则整个文件当做一行处理。

find java6-src -name '*.java' |xargs cat | tr '\r' '\n'|
grep '[ \t\n]*throw[ \t\n]\+new' > java6.thrown.txt
find spring3-src/projects -name '*.java'|xargs cat | tr '\r' '\n'|
grep '[ \t\n]*throw[ \t\n]\+new' > spring3.thrown.txt
wc -l *.txt
 10959 java6.thrown.txt
  2994 spring3.thrown.txt
 13953 total

sed -n 's/.*throw[ \t]\+new[ \t]\+\([^(]\+\).\+/\1/p' java6.thrown.txt |
sort |uniq -c | sort -nr >java6.exception.txt
sed -n 's/.*throw[ \t]\+new[ \t]\+\([^(]\+\).\+/\1/p' spring3.thrown.txt |
sort |uniq -c | sort -nr >spring3.exception.txt

head java6.exception.txt
   2153 IllegalArgumentException
    795 NullPointerException
    438 RuntimeException
    295 UnsupportedOperationException
    291 DOMException
    280 IllegalStateException
    245 IOException
    219 IndexOutOfBoundsException
    185 ReadOnlyBufferException
    161 InternalError
head spring3.exception.txt
    574 IllegalStateException
    561 IllegalArgumentException
    217 UnsupportedOperationException
    128 RuntimeException
     66 InvalidResultSetAccessException
     62 SpelEvaluationException
     56 OperationNotSupportedException
     55 TransactionSystemException
     52 InvalidDataAccessApiUsageException
     47 ServletException

4. 低级习惯
  1. 作为流程控制。违法异常设计初衷。
  2. 私吞异常。包括空catch块或printStackTrace等伪处理。异常,要么处理好,要么不处理。
  3. 异常覆盖。catch或finally块内引发异常,覆盖源头问题,信息丢失。

<java> 异常转换与防覆盖 
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
boolean succeed = false;
List r = null;
S2AttributeReportDao dao = null;
try{
   dao = new S2AttributeReportDao();
   r = dao.getNewNameReportCandidates(jicAccountDate);
   succeed = true;
}catch(DaoException e){
   throw new ServiceException(e);
}finally{
   if(dao != null){
       try{
           dao.dispose();
       }catch(DaoException de){
           if(succeed){
               throw new ServiceException(de);
           }
       }
   }
}
return r==null?new ArrayList():r;

5. 参考资料
  • ST Sun的Java指南
  • EJ Effective Java 第2版(ISBN 978-7-111-25583-3,机械工业出版社)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值