java编程常见错误三[转帖]_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4007 | 回复: 0   主题: java编程常见错误三[转帖]        下一篇 
lynda
注册用户
等级:上尉
经验:570
发帖:49
精华:0
注册:2012-8-7
状态:离线
发送短消息息给lynda 加好友    发送短消息息给lynda 发消息
发表于: IP:您无权察看 2012-8-8 17:17:53 | [全部帖] [楼主帖] 楼主

不指定超时时间

错误的代码:

  1. Socket socket = ...   
  2. socket.connect(remote);   
  3. InputStream in = socket.getInputStream();   
  4. int i = in.read();  

这种情况在工作中已经碰到不止一次了。个人经验一般超时不要超过20s。这里有一个问题,connect可以指定超时时间,但是read无法指定超时时间。但是可以设置阻塞(block)时间。

正确的写法:

  1. Socket socket = ...   
  2. socket.connect(remote, 20000); // fail after 20s   
  3. InputStream in = socket.getInputStream();   
  4. socket.setSoTimeout(15000);   
  5. int i = in.read();  

另外,文件的读取(FileInputStream, FileChannel, FileDescriptor, File)没法指定超时时间, 而且IO操作均涉及到本地方法调用, 这个更操作了JVM的控制范围,在分布式文件系统中,对IO的操作内部实际上是网络调用。一般情况下操作60s的操作都可以认为已经超时了。为了解决这些问题,一般采用缓存和异步/消息队列处理。

频繁使用计时器

错误代码:

  1. for (...) {   
  2.  long t = System.currentTimeMillis();   
  3.  long t = System.nanoTime();   
  4.  Date d = new Date();   
  5.  Calendar c = new GregorianCalendar();   

每次new一个Date或Calendar都会涉及一次本地调用来获取当前时间(尽管这个本地调用相对其他本地方法调用要快)。
如果对时间不是特别敏感,这里使用了clone方法来新建一个Date实例。这样相对直接new要高效一些。

正确的写法:

  1. Date d = new Date();   
  2. for (E entity : entities) {   
  3.  entity.doSomething();   
  4.  entity.setUpdated((Date) d.clone());   

如果循环操作耗时较长(超过几ms),那么可以采用下面的方法,立即创建一个Timer,然后定期根据当前时间更新时间戳,在我的系统上比直接new一个时间对象快200倍:

  1. private volatile long time;   
  2. Timer timer = new Timer(true);   
  3. try {   
  4.  time = System.currentTimeMillis();   
  5.  timer.scheduleAtFixedRate(new TimerTask() {   
  6.  public void run() {   
  7.  time = System.currentTimeMillis();   
  8.  }   
  9.  }, 0L, 10L); // granularity 10ms   
  10.  for (E entity : entities) {   
  11.  entity.doSomething();   
  12.  entity.setUpdated(new Date(time));   
  13.  }   
  14. } finally {   
  15. timer.cancel();   

捕获所有的异常

错误的写法:

  1. Query q = ...   
  2. Person p;   
  3. try {   
  4.  p = (Person) q.getSingleResult();   
  5. } catch(Exception e) {   
  6. p = null;   

这是EJB3的一个查询操作,可能出现异常的原因是:结果不唯一;没有结果;数据库无法访问,而捕获所有的异常,设置为null将掩盖各种异常情况。

正确的写法:

  1. Query q = ...   
  2. Person p;   
  3. try {   
  4.  p = (Person) q.getSingleResult();   
  5. } catch(NoResultException e) {   
  6.  p = null;   

忽略所有异常

错误的写法:

  1. try {   
  2.  doStuff();   
  3. } catch(Exception e) {   
  4. log.fatal("Could not do stuff");   
  5. }   
  6. doMoreStuff(); 

这个代码有两个问题, 一个是没有告诉调用者, 系统调用出错了. 第二个是日志没有出错原因, 很难跟踪定位问题。

正确的写法:

  1. try {   
  2.  doStuff();   
  3. } catch(Exception e) {   
  4. throw new MyRuntimeException("Could not do stuff because: "+ e.getMessage, e);   

重复包装RuntimeException

错误的写法:

  1. try {   
  2.  doStuff();   
  3. } catch(Exception e) {   
  4. throw new RuntimeException(e);   

正确的写法:

  1. try {   
  2.  doStuff();   
  3. } catch(RuntimeException e) {   
  4.  throw e;   
  5. } catch(Exception e) {   
  6. throw new RuntimeException(e.getMessage(), e);   
  7. }   
  8. try {   
  9.  doStuff();   
  10. } catch(IOException e) {   
  11.  throw new RuntimeException(e.getMessage(), e);   
  12. } catch(NamingException e) {   
  13.  throw new RuntimeException(e.getMessage(), e);   

不正确的传播异常

错误的写法:

  1. try {   
  2. } catch(ParseException e) {   
  3.  throw new RuntimeException();   
  4.  throw new RuntimeException(e.toString());   
  5.  throw new RuntimeException(e.getMessage());   
  6.  throw new RuntimeException(e);   

主要是没有正确的将内部的错误信息传递给调用者. 第一个完全丢掉了内部错误信息, 第二个错误信息依赖toString方法, 如果没有包含最终的嵌套错误信息, 也会出现丢失, 而且可读性差. 第三个稍微好一些, 第四个跟第二个一样。

正确的写法:

  1. try {   
  2. } catch(ParseException e) {   
  3.  throw new RuntimeException(e.getMessage(), e);   




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论