当前位置:首页 > 开发 > 编程语言 > Java > 正文

Java异常那些不得不说的事

发表于: 2014-11-29   作者:白糖_   来源:转载   浏览:
摘要: 一、在finally块中做数据回收操作 比如数据库连接都是很宝贵的,所以最好在finally中关闭连接。 JDBCAgent jdbc = new JDBCAgent(); try{ jdbc.excute("select * from ctp_log"); }catch(SQLException e){ ... }finally{ jdbc.close();

一、在finally块中做数据回收操作

比如数据库连接都是很宝贵的,所以最好在finally中关闭连接。

JDBCAgent jdbc = new JDBCAgent();
try{
jdbc.excute("select * from ctp_log");
}catch(SQLException e){
...
}finally{
jdbc.close();
}

 

 

二、不要在异常finally块中定义返回值

如下代码,虽然有很多返回值,但如果真的执行,该代码的返回值永远是3,因为finally是最终执行代码,将其它返回值全部覆盖了!

try{  
  if(x = 1){  
    return throw new RuntimeException();  
  }else{  
    return 1;  
  }  
}catch(Exception e){  
  return 2;  
}finally{  
  return 3;  
} 

 

 

三、覆写Exception的fillInStackTrace方法能提高异常性能

异常性能差是因为fillInStackTrace方法,该方法是带锁的并且需要填充线程异常栈信息。

而我们的业务类异常是不需要记录异常栈的,可以考虑覆写fillInStackTrace方法减小性能开支(据说覆写该方法能提高10倍性能)。

(注:什么是业务类,参照第四点)

public class AccountException extends Exception {
    public Throwable fillInStackTrace() {  
        return this;  
    }
}

 

 

四、业务上的错误使用异常更加OOP

以登录为例,简单的登录方法通过返回boolean即可确认是否登录成功,但如果功能日趋复杂怎么办?通过抛出业务类异常的方式来解析错误信息可读性非常好。

try{
  userManager.login(account,passowrd,identify);
}catch(AccountException e){  
  //账号出错  
}catch(PasswordException e){  
  //密码出错  
}catch(IdentifyException e){
  //验证码错误
}catch(AccountDisableException e){
  //账号被禁用
}

 

 

五、使用正确的log记录异常信息

Log logger = LogFactory.getLog(Demo.class);
try{
  
}catch(SQLException e){
 throw new BusinessException(e);           //√发生该异常会影响后续数据完整性的时候,应该抛出中止操作
 logger.error(e.getLocalizedMessage(),e);  //√记录完整的log日志方便调试
 log.error(e);                             //×这种记录方式只能记录很少的异常信息(连异常发生的位置都没有,记了白记)
 e.printStackTrace();                      //×仅仅将异常打到控制台,开发调试还可以,一旦到生产环境就很难跟踪异常
 System.out.print(e);                      //×同上
}

 

 

六、除了记录异常,记得记录详细参数信息

很多时候通过logger.error(e.getLocalizedMessage(),e)这种记录日志的方式都不一定分析出异常原因。

比如出现一个SQL异常,log日志可能会这样提示:ORA-00936: 缺少表达式。试问这样的错误你能分析这句SQL到底哪儿出了问题吗?不能!所以记录日志的时候最好是把SQL及参数都打印出来,如下例所示。

但记录日志要有分寸,别把客户的机密信息记录出来,如果被发现,我们会负责的!

public List find(Long id,String name){
  String sql = ......;
  try{
  JdbcAgent.excute(sql);
  }catch(Exception e){
  logger.error("sql异常:"+sql+" 参数ID:"+id+",参数name:"+name,e);
  }
}

 

(注:作为研发你可能会说:我通过Eclipse debugger调试就可以知道原因了。但从长远考虑:假如系统已经部署到客户环境上,他们允许你debugger调试吗?不能!所以最好的求助工具就是详细的log日志!)

 

七、从子到父顺序捕获异常

如下所示,假如抛出的是BusinessException异常,那么第二个catch就能捕获到。

如果catch(Exception e)在catch(BusinessException e)之前,则该异常会被catch(Exception e)捕获而不会进catch(BusinessException e)。

try{

}catch(RuntimeException e){

}catch(BusinessException e){//BusinessException extends Exception

}catch(Exception e){

}

 

 

八、使用isInfoEnabled和isDebugEnabled

在看spring和apache等开源体系下的代码时,你会发现在记录log日志时总是看到如下风格的代码:

if (logger.isDebugEnabled()) {
    logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
}
if (logger.isInfoEnabled()) {
	long elapsedTime = System.currentTimeMillis() - startTime;
	logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
}

 

为什么记录debug和info日志前要加个判断?其实原因很简单:提高效率!如上代码所示,在记录日志时进行了字符串拼接,要知道这是会消耗一定资源的。假如当前log日志级别是error,则debug和info是不会被输出的,如果加了if判断则log.debug/info中的字符串拼接就不会执行,自然提高了效率。

在小系统看不出差距,但如果是高并发的系统下,少执行一句代码能明显减小服务器的压力,精细化的代码是有必要的!

 

注意:下面这样的代码是提高不了性能的,因为在if之前就已经准备好log信息:

long elapsedTime = System.currentTimeMillis() - startTime;
String info = "Root WebApplicationContext: initialization completed in " + elapsedTime + " ms";
if (logger.isInfoEnabled()) {
	logger.info(info);
}

 

Java异常那些不得不说的事

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
今天有同事问我关于Observer模式的一个问题,说观察者(Observer)为什么要依赖于主题(Subject),如下
说到C语言,就不得不说它的继承者——C++语言。众所周知,C++语言是在C语言的基础上,添加了面向对
昨天微软终于如期发布了VS2010 Beta的试用 (Beta版没有离线的MSDN,只有在线MSDN) 在本文中我将集
在很久很久以前,刚有浏览器和网页的时候,web开发者发现了一个问题,我必须要在客户端这边保存一些
说到C语言,就不得不说它的继承者——C++语言。众所周知,C++语言是在C语言的基础上,添加了面向对
2010-11-21 18:32 提起PQ,就算没用过的也应该听过,PowerQuest PartitionMagic是它的全名,容易混
说到C语言,就不得不说它的继承者——C++语言。众所周知,C++语言是在C语言的基础上,添加了面向对
说到C语言,就不得不说它的继承者——C++语言。众所周知,C++语言是在C语言的基础上,添加了面向对
 从開始学习VB,就听说过“异常”,认为异常处理就是加上try..catch,不让错误抛出给用户,到此
 从开始学习VB,就听说过“异常”,觉得异常处理就是加上try..catch,不让错误抛出给用户,到此
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号