关于异常处理的不良习惯和改正方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wengwuhua/article/details/79053740

关于异常处理的不良习惯

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"));  
 }  
 conn.close(); // ⑶  
 out.close();  
}  
catch(Exception ex) // ⑵  
{  
 ex.printStackTrace(); //⑴,⑷  
} 

上面的例子共有6个不好的编程习惯问题:
1.丢弃异常(15-18行)
这段代码捕获了异常却不作任何处理,可以算得上Java编程中的杀手。如果你看到了这种丢弃(而不是抛出)异常的情况,可以百分之九十九地肯定代码存在问题(在极少数情况下,这段代码有存在的理由,但最好加上完整的注释,以免引起别人误解)。
有4种该正的选择:
* 处理异常。针对该异常采取一些行动,例如修正问题、提醒某个人或进行其他一些处理,要根据具体的情形确定应该采取的动作。再次说明,调用printStackTrace算不上已经“处理好了异常”。
* 重新抛出异常。处理异常的代码在分析异常之后,认为自己不能处理它,重新抛出异常也不失为一种选择。
* 把该异常转换成另一种异常。大多数情况下,这是指把一个低级的异常转换成应用级的异常(其含义更容易被用户了解的异常)。
* 不要捕获异常。
结论一:既然捕获了异常,就要对它进行适当的处理。不要捕获异常之后又把它丢弃,不予理睬.

2.不指定具体的异常(15行)
catch语句表示我们预期会出现某种异常,而且希望能够处理该异常。异常类的作用就是告诉Java编译器我们想要处理的是哪一种异常。所以一定要指明具体的异常,不要直接用Exception()。
结论二:在catch语句中尽可能指定具体的异常类型,必要时使用多个catch。不要试图处理所有可能出现的异常。

3.占用资源不释放(3-14行)
异常改变了程序正常的执行流程。这个道理虽然简单,却常常被人们忽视。如果程序用到了文件、Socket、JDBC连接之类的资源,即使遇到了异常,也要正确释放占用的资源。而上面如果发生了异常,则释放资源的语句没有执行到释放不了,此时应该利用finally关键字来执行。当然,编写finally块应当多加小心,特别是要注意在finally块之内抛出的异常??这是执行清理任务的最后机会,尽量不要再有难以处理的错误。
结论三:保证所有资源都被正确释放。充分运用finally关键词。

4.不说明异常的详细信息(3-18行)
printStackTrace的堆栈跟踪功能显示出程序运行到当前类的执行流程,但只提供了一些最基本的信息,未能说明实际导致错误的原因,同时也不易解读。因此,在出现异常时,最好能够提供一些文字信息,例如当前正在执行的类、方法和其他状态信息,包括以一种更适合阅读的方式整理和组织printStackTrace提供的信息。
结论四:在异常处理模块中提供适量的错误原因信息,组织错误信息使其易于理解和阅读。

5.过于庞大的try块(3-14行)
把大量的代码放在try块中,当出现问题时很难定位到时哪一个语句导致的异常,正确的做法应该是分离各个可能出现的异常段落并分别捕获异常。
结论五:尽量减小try块的体积。

6.输出数据不完整(7-11行)
不完整的数据是Java程序的隐形杀手。仔细观察这段代码,考虑一下如果循环的中间抛出了异常,会发生什么事情?使用这些数据的人或设备将收到一份不完整的(因而也是错误的)数据,却得不到任何有关这份数据是否完整的提示。较为理想的处置办法是向输出设备写一些信息,声明数据的不完整性;另一种可能有效的办法是,先缓冲要输出的数据,准备好全部数据之后再一次性输出。
结论六:全面考虑可能出现的异常以及这些异常对执行流程的影响。若导致数据不完整该如何处理。
改写后:

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());  
  }  
 }  
}  

结语:当然具体问题具体对待,以上也只是一部分内容。总之要养成良好的编程习惯和代码风格,注意细节的处理!

猜你喜欢

转载自blog.csdn.net/Wengwuhua/article/details/79053740