现在大多数高级语言都支持异常处理机制,而C语言是根据返回值(一般是定义为宏的整型数,如EXIT_FAILURE)判断错误类型加上goto语言处理异常,在linux内核中有大量goto语句的出现。而java支持异常处理,异常会改变程序运行顺序,也就说改变程序顺序的有if语句(循环也算是间接的if)、函数调用(或方法调用)和return语句、异常等。首先看一段代码:
OutputStream out = ...; java.sql.Connection conn = ...; try { Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("select uid, name from user"); while (rs.next()) { out.println(rs.getString("uid") + ": " + rs.getString("name")); } conn.close(); out.close(); } catch (Exception e) { e.printStackTrace(); }
以上代码是http://www.blogjava.net/freeman1984/archive/2013/07/26/148850.html中关于异常处理习惯的反例,不过这在大多数java程序员中经常出现的问题。
1,一个Exception 试图处理所有的异常,这是相当之不科学的,一个好的习惯是根据不同的异常类型做不同的处理,通过不同的catch块并指定具体的异常处理具体类,作不同的异常,并且catch异常类的顺序是有讲究的,一般先子类,然后再基类,在所有已知具体类都catch后,最后最好在捕获一个Exception类异常,防止可能由于疏忽丢了某些异常。如果需要同时捕获几个异常做统一处理,java7中支持catch (xx1Exception e | xx2Wxception 2 ...)的语法,可以同时对多个类型的异常做统一处理。
2,代码中并没有处理异常,而只是打印一个异常调用栈,并没有具体作处理,一般应该具体输出些日志信息,或者抛出自定义异常,并做一些工作。只要捕获了异常,就要好好处理,否则就不要捕获。
3, 资源的释放一般在finally块中处理,而不应该放在try块中,finally块不管异常是否出现,都会在整个try块退出前执行,一般执行一些清理工作,保证资源正确释放。当然在java7中如果实现了java.lang.AutoCloseable接口,则jvm会自动调用close方法进行资源释放。
4,try块不能太大,有时为了图方便,把一大片代码放入一个try块中,这样不仅出现代码混乱,而且也不利于针对具体异常作处理。
最后修改后的代码:
OutputStream out = ...; java.sql.Connection conn = ...; try { Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery("select uid, name from user"); while (rs.next()) { out.println(rs.getString("uid") + ": " + rs.getString("name")); } } catch (SQLException e) { log("..."); throw new ApplicationException("..."); } catch (IOException e) { log("..."); throw new ApplicationException("..."); } catch (Exception e) { //do something else } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { // do something else } } if (out != null) { try { out.close(); } catch (IOException e) { // do something else } } }
总之要好好利用java的异常处理机制,不能图方便,只为能正确编译,而把一大片代码放入一个块,然后捕获一个Exception类。
参考:http://www.blogjava.net/freeman1984/archive/2013/07/26/148850.html