首页 > 代码库 > 程序健壮性之“异常处理”
程序健壮性之“异常处理”
定义
异常处理(Exceptional Handing)是代替Error Code的新法,分离了接收和处理错误代码。
基本模型
终止模型:将假设错误非常关键,将以致于程序无法返回到异常的地方继续执行,一旦异常被跑出就 表明错误已无法挽回,不能再继续执行。
恢复模型:异常处理程序的工作是修正错误,然后重新尝试调动出问题的方法,并认为第二次能够成功。
异常处理原则
反面示例:
1 OutputStreamWriter out = ... 2 java.sql.Connection conn = ... 3 try { // ⑸ 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery( "select uid, name from user"); 6 while (rs.next()) { 7 out.println("ID:" + rs.getString("uid") +",姓名:" + rs.getString("name")); }// ⑹ 8 conn.close(); // ⑶ 9 out.close(); }
10 catch(Exception ex){// ⑵ 11 ex.printStackTrace();}//⑴,⑷
1 不要轻易丢弃异常
如(1),仅仅printStackTrace是不够的,异常(几乎)总是意味者某些事情不对劲了但是作为程序员对这种求救信号保持沉默和无动于衷。
对于捕获到的异常通常有4个选择:
a、处理异常。针对改异常采取行动,如修正问题、给出提醒。
b、分析处理后继续抛出异常。
c、转换异常。将一个低级异常转换成应用级异常
2 要指定具体异常
如果不指定具体异常,系统就会尝试去判断所有的异常可能,这样会造成性能的损耗。在这个例子中,最想要捕获的异常是SQLException,另外一个异常是IOExcepiton,。显然在同一个catch块里处理这两个异常是不合适的。所以合适的做法是catch(SQLException){}catch(IOExcepiton){}。至于其他的异常留给上层调用处理
3 占用资源不释放
异常改变了程序的正常执行流程。这个道理很简单,却容易被忽视。如果程序用到了文件、Socket、JDBC连接之类的资源,即使遇到异常,也要正确释放占用的资源。为此可以用finally来保证资源的正确释放。但是一定要注意在finally里不要发生异常,因为finally是执行清理任务的最后机会。
4 说明异常详细信息
简单的pringStackTrace给调试程序带来困难,没有具体明确的说明,即使发现错误也无法快速的定位和判断错误原因。所以出现异常时,最后能够提供一些文字说明,比如当前正在执行的类、方法和其他状态信息。
5 过于庞大的try块
经常把大量的代码放入单个try块不是个好习惯。一旦这么做了,就意味这你不愿意去仔细分析这 段代码会抛出什么异常,也不会为这些异常做一些针对性的处理。这样的话就违反了原则1、2、 4。
6 输出数据不完整
在这段循环中输出数据发生了异常,catch块执行,循环中断,那么已经输出的数据怎么办?用户得到一份不完整的数据?还是系统产生了脏数据?较为理想的做法是使用缓存或者使用事务处理。
最后给出优化过的代码:
OutputStreamWriter out = ... java.sql.Connection conn = ... try { Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery( "select uid, name from user"); while (rs.next()) { out.println("ID:" + rs.getString("uid") + ",姓名: " + rs.getString("name")); } } catch(SQLException sqlex) { out.println("警告:数据不完整");
throw new ApplicationException("读取数据时出现SQL错误", sqlex); }
catch(IOException ioex) {
throw new ApplicationException("写入数据时出现IO错误", ioex); }
finally {
if (conn != null) {
try { conn.close(); }
catch(SQLException sqlex2) {
System.err(this.getClass().getName() + ".mymethod - 不能关闭数据库连接: " + sqlex2.toString()); } }
if (out != null) {
try { out.close(); }
catch(IOException ioex2) {
System.err(this.getClass().getName() + ".mymethod - 不能关闭输出文件" + ioex2.toString()); } } }
程序健壮性之“异常处理”