捕获所有的异常
错误的代码:
Query q = ... Person p; try { p = (Person) q.getSingleResult(); } catch(Exception e) { p = null; }
这是EJB3的一个查询操作, 可能出现异常的原因是: 结果不唯一; 没有结果; 数据库无法访问, 而捕获所有的异常, 设置为null将掩盖各种异常情况.
正确的写法:
Query q = ... Person p; try { p = (Person) q.getSingleResult(); } catch(NoResultException e) { p = null; }
忽略所有异常
错误的代码:
try { doStuff(); } catch(Exception e) { log.fatal("Could not do stuff"); } doMoreStuff();
这个代码有两个问题, 一个是没有告诉调用者, 系统调用出错了. 第二个是日志没有出错原因, 很难跟踪定位问题.
正确的写法:
try { doStuff(); } catch(Exception e) { throw new MyRuntimeException("Could not do stuff because: "+ e.getMessage, e); }
重复包装RuntimeException
错误的代码:
try { doStuff(); } catch(Exception e) { throw new RuntimeException(e); }
正确的写法:
try { doStuff(); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new RuntimeException(e.getMessage(), e); } try { doStuff(); } catch(IOException e) { throw new RuntimeException(e.getMessage(), e); } catch(NamingException e) { throw new RuntimeException(e.getMessage(), e); }
不正确的传播异常
错误的代码:
try { } catch(ParseException e) { throw new RuntimeException(); throw new RuntimeException(e.toString()); throw new RuntimeException(e.getMessage()); throw new RuntimeException(e); }
主要是没有正确的将内部的错误信息传递给调用者. 第一个完全丢掉了内部错误信息, 第二个错误信息依赖toString方法, 如果没有包含最终的嵌套错误信息, 也会出现丢失, 而且可读性差. 第三个稍微好一些, 第四个跟第二个一样.
正确的写法:
try { } catch(ParseException e) { throw new RuntimeException(e.getMessage(), e); }
用日志记录异常
错误的代码:
try { ... } catch(ExceptionA e) { log.error(e.getMessage(), e); throw e; } catch(ExceptionB e) { log.error(e.getMessage(), e); throw e; }
一般情况下在日志中记录异常是不必要的, 除非调用方没有记录日志.
异常处理不彻底
错误的代码:
try { is = new FileInputStream(inFile); os = new FileOutputStream(outFile); } finally { try { is.close(); os.close(); } catch(IOException e) { /* we can't do anything */ } }
is可能close失败, 导致os没有close
正确的写法:
try { is = new FileInputStream(inFile); os = new FileOutputStream(outFile); } finally { try { if (is != null) is.close(); } catch(IOException e) {/* we can't do anything */} try { if (os != null) os.close(); } catch(IOException e) {/* we can't do anything */} }
捕获不可能出现的异常
错误的代码:
try { ... do risky stuff ... } catch(SomeException e) { // never happens } ... do some more ...
正确的写法:
try { ... do risky stuff ... } catch(SomeException e) { // never happens hopefully throw new IllegalStateException(e.getMessage(), e); // crash early, passing all information } ... do some more ...