用日志记录异常
错误的写法:
- 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 ... 
transient的误用
错误的写法:
- public class A implements Serializable {   
-  private String someState;   
-  private transient Log log = LogFactory.getLog(getClass());   
-  
-  public void f() {   
-  log.debug("enter f");   
-  ...   
-  }   
- } 
这里的本意是不希望Log对象被序列化. 不过这里在反序列化时, 会因为log未初始化, 导致f()方法抛空指针, 正确的做法是将log定义为静态变量或者定位为具备变量。
正确的写法:
- public class A implements Serializable {   
-  private String someState;   
-  private static final Log log = LogFactory.getLog(A.class);   
-  
-  public void f() {   
-  log.debug("enter f");   
-  ...   
-  }   
- }   
- public class A implements Serializable {   
-  private String someState;   
-  
-  public void f() {   
-  Log log = LogFactory.getLog(getClass());   
-  log.debug("enter f");   
-  ...   
-  }   
- } 
不必要的初始化
错误的写法:
- public class B {   
-  private int count = 0;   
-  private String name = null;   
-  private boolean important = false;   
- } 
这里的变量会在初始化时使用默认值:0, null, false, 因此上面的写法有些多此一举。
正确的写法:
- public class B {   
-  private int count;   
-  private String name;   
-  private boolean important;   
- } 
最好用静态final定义Log变量
- private static final Log log = LogFactory.getLog(MyClass.class);  
这样做的好处有三:
- 可以保证线程安全
- 静态或非静态代码都可用
- 不会影响对象序列化
选择错误的类加载器
错误的代码:
- Class clazz = Class.forName(name);   
- Class clazz = getClass().getClassLoader().loadClass(name);  
这里本意是希望用当前类来加载希望的对象, 但是这里的getClass()可能抛出异常, 特别在一些受管理的环境中, 比如应用服务器, web容器, Java WebStart环境中, 最好的做法是使用当前应用上下文的类加载器来加载。
正确的写法:
- ClassLoader cl = Thread.currentThread().getContextClassLoader();   
- if (cl == null) cl = MyClass.class.getClassLoader(); // fallback   
- Class clazz = cl.loadClass(name);  
反射使用不当
错误的写法:
- Class beanClass = ...   
- if (beanClass.newInstance() instanceof TestBean) ...  
这里的本意是检查beanClass是否是TestBean或是其子类, 但是创建一个类实例可能没那么简单, 首先实例化一个对象会带来一定的消耗, 另外有可能类没有定义默认构造函数. 正确的做法是用Class.isAssignableFrom(Class) 方法。
正确的写法:
- Class beanClass = ...   
- if (TestBean.class.isAssignableFrom(beanClass)) ...