当前位置:  技术问答>java相关

found an article about returning null or throwing exception.

    来源: 互联网  发布时间:2015-06-15

    本文导语:  China    dW 中国所有内容.................dW 中国技术专区: 组件技术 Java 技术 Linux XML.................dW 中国特别专题: 安全 Unicode 网站架构.................IBM 全部内容       搜索帮助            IBM 主页 ...

China  
 dW 中国所有内容.................dW 中国技术专区: 组件技术 Java 技术 Linux XML.................dW 中国特别专题: 安全 Unicode 网站架构.................IBM 全部内容      
搜索帮助 
 
 
      IBM 主页   |   产品与服务   |   支持与下载   |   个性化服务 
 
 
 
 
 
 
IBM : developerWorks 中国网站 : Java : 所有的文章    
 
 
 诊断 Java 代码空标志错误模式  英文原文  
 
 
   
内容: 
 
空标志错误模式 
起因 
预防措施 
总结 
参考资料 
关于作者 
对本文的评价 
 
 
相关内容: 
 
Dangling Composite 错误模式 
错误模式:介绍 
诊断 Java 代码其他部分 
 
 
 
 
避免使用空指针作为标志以防止出现异常 
Eric E. Allen
软件工程师,Cycorp, Inc.
2001 年 3 月

为开发健壮的程序,我们经常用空指针代替异常情况,但这实际上却把控制流限制在方法调用和返回的普通方式,同时也隐藏了异常情况发生的迹象。在这篇专栏里,Eric Allen 展示了这种错误模式(他称之为空标志错误模式)怎样产生难以调试的意外结果。和我们讨论过的其它错误模式一样,您可以应用某种编程技巧来减少这种错误的出现。
空标志错误模式
在我的上一篇文章中,我说明了用空指针代替各种不同基本类型的数据是如何成为引起 NullPointerException 异常最普遍的原因之一的。这一次,我将说明用空指针代替异常情况怎么也会导致问题的出现。在 Java 程序中,异常情况通常是通过抛出异常,并在适当的控制点捕获它们来进行处理。但是经常看到的方法是通过返回一个空指针值来表明这种情况(以及,可能打印一条消息到 System.err)。如果调用方法没有明确地检查空指针,它可能会尝试丢弃返回值并触发一个空指针异常。

您可能会猜想,之所以称这种模式为空标志错误模式,是因为它是不一致地使用空指针作为异常情况的标志引起的。

起因
让我们来考虑一下下面的这个简单的桥类(从 BufferedReaders 到 Iterators):

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Iterator;


public class BufferedReaderIterator implements Iterator {

  private BufferedReader internal;

  public BufferedReaderIterator(BufferedReader _internal) {
    this.internal = _internal;
  }

  public boolean hasNext() {
    try {
    
      boolean result = true;

      // Let's suppose that lines in the underlying input stream are known
      // to be no greater than 80 characters long.
      internal.mark(80);

      if (this.next() == null) {
        result = false;
      }
      internal.reset();
      return result;
    }
    catch (IOException e) {
      System.err.println(e.toString());
      return false;
    }
  }

  public Object next() {
    try {
      return internal.readLine();
    }
    catch (IOException e) {
      System.err.println(e.toString());
      return null;
    }
  }

  public void remove() {

    // This iterator does not support the remove operation.
    throw new UnsupportedOperationException();
  }

}

 

因为这个类作为 Iterator 接口的桥接实现,代码必须从 BufferedReader 捕获 IOException 异常。每一种方法通过返回某个缺省值来处理 IOException。对于 hasNext,返回 false 值。这是合理的,因为如果 IOException 异常被抛出,客户就不应该指望能从 Iterator 检索到另一个元素。另一方面,在 IOException 异常(因为它取决于 internal.readLine() 的返回值)和 internal 是空的情况下,next 都返回 null。但这不是 Iterator 对象的客户所期待的。正常情况下,在没有更多元素的 Iterator 上调用 next 时,会抛出一个 NoSuchElementException 异常。如果我们的 Iterator 的客户依赖于这种行为,它很可能会尝试丢弃从调用 next 返回的空指针,结果导致 NullPointerException 异常。

不管 NullPointerException 异常什么时候出现,都要对如上所述的情况作检查。这种错误模式的出现很普遍。

预防措施
尽管这种错误模式经常出现,使用空标志仍是非常没有根据的(与上例的情况一样)。让我们来重写 next,使它如我们期望的一样抛出 NoSuchElementException 异常:

 public Object next() {
    try {
      String result = internal.readLine();
      if (result == null) {
    throw new NoSuchElementException();
      }
      else {
    return result;
      }
    }
    catch (IOException e) {
    
      // The original exception is included in the message to notify the 
      // client that an IOException has occurred.
      throw new NoSuchElementException(e.toString());
    }
  }



 

请注意:要使其余的代码能使用修改过的方法,我们还必须:

导入 java.util.NoSuchElementException。 
修正 hasNext,使其不再调用 next 来进行测试。最简单的修正方法是只要直接调用 internal.readLine()。 



另一种处理 IOException 异常的方法是捕获它们,并代替它们抛出 RuntimeException 异常。决定这样做是基于对目标平台上预计 IOException 异常出现频率的估计。如果很频繁,那么您可能想试着从中恢复。

调用这个新 next 方法的任何代码可能都不得不处理抛出的 NoSuchElementException 异常。(当然,代码可以简单地选择忽略它们并允许程序异常终止。)如果这样,与原始代码抛出的 NullPointerException 异常相比,产生的错误消息和抛出异常的位置所提供的信息要丰富得多。如果抛出的异常是检查过的异常(比如 IOException),那么它会更有用,因为除非处理了异常,否则类的客户代码将不编译。利用这种方法,我们甚至可以在程序运行前排除某些错误发生的可能性。但是,在这个示例中,不破坏 Iterator 接口,就不能抛出这样一个检查过的异常。因此,为了重复使用在 Iterators 上运行的代码,我们牺牲了一些静态检查。静态检查的目的和重复使用的目的之间的这种矛盾是很普遍的。

总结
在我完成这篇文章前,我要提醒许多经常使用空标志的程序员注意。许多程序员会争辩说这会使他们的程序更“健壮”。毕竟,他们可能会说,健壮的系统能够适当地处理不同的情况,而不是一遇到小问题就抛出异常。但是这种争辩忽视了这样一种事实,即异常是增强代码健壮性的有力工具,它允许在异常情况下控制能快速传送到最适合控制的位置。另一方面,空标志的使用把控制流限制在方法调用和返回的普通方式(当然,一直到整个程序崩溃)。此外,这样使用空标志,程序员有效地掩盖了异常情况出现位置的迹象。谁知道空指针在被丢弃前从方法到方法传递了多远?这只能使得诊断错误以及确定怎样修正它们更加困难。经验证明这种代码经常中断。我们首要关注的应该是避免这种困惑,使诊断尽可能容易。因此,作为准则,我努力编写可以尽快通知异常情况的代码,并且尝试着仅从没有指示程序错误的异常情况中恢复。

即使在代码中尽量避免使用空标志,您仍要不可避免地处理使用了空标志的旧代码。事实上,许多 Java 类库本身,比如我们上面使用过的 Hashtable 类和 BufferedReader 类都用了空标志。当使用这样的类时,您可以通过在执行前,显式检查操作是否将返回空来避免错误。例如,对于 Hashtables,我总是在调用 get 之前用 containsKey 进行测试。但是,尽管采用这种预防手段,这种错误模式仍然是最常碰到的错误模式之一。

下面是本周的错误模式的小结:

模式:空标志 
症状:使用空指针作为异常情况的标志的代码块报告 NullPointerException 异常。 
起因:调用方法没有检查作为返回值的空指针。 
治疗和预防措施:抛出异常来报告异常情况。 



在下一篇文章中,我将讨论与类强制转换异常有关的错误模式。

参考资料

请务必阅读 Eric Allen 的前一个关于错误模式的诊断 Java 代码专栏: 
The Dangling Composite bug pattern(developerWorks,2001 年 3 月) 
错误模式:介绍(developerWorks ,2001 年 2 月) 
一种防止异常情况处理不一致的方法是面向表征的编程: 一种将程序的经常绕过模块边界的部分模块化的编程风格。请查看 AspectJ,Java 语言的一种面向表征的扩展,带有支持许多流行的 Java IDE 的实现。 
静态确定可能出现空指针异常的方法是一种被称为 set-based analysis 的技术。The Carnegie Mellon School of Computer Science 网站为这种方法提供了简短介绍,同时还提供与本文相关的一些技术出版物的链接。 
DePaul 大学的软件工程部已经在自动化定理方面做了一些工作,在 Java 代码中侦测出空指针异常。 
访问 Patterns 主页,获取关于设计模式以及怎样使用它们的好的介绍。 
请查看 JUnit,通过将代码 "test-infested" 来捕捉更多的错误。 


关于作者
Eric Allen 毕业于 Cornell 大学,曾获得计算机科学和数学的学士学位。目前是 Cycorp, Inc. 的 Java 软件开发的带头人以及 Rice 大学编程语言小组的半工半读研究生。他的研究涉及正规语义模型和 Java 语言的扩展,都是在源代码和字节代码的级别上的。目前,他正在为 NextGen 编程语言实现一种从源代码到字节代码的编译器,这也是 Java 语言的泛型运行时类型的一种扩展。 
  


到页首  
 
 
   您对这篇文章的看法如何?  
真棒!(5) 好材料 (4) 一般;尚可 (3) 需提高 (2) 太差! (1) 

建议?


 
 
(c) Copyright IBM Corp. 2001, (c) Copyright IBM China 2001, All Right Reserved 
  关于 IBM  |  隐私条约  |  法律条款  |  联系 IBM 

|
呵呵,ajoo兄终于找到强有力的支持者了:)

================================================================
Someone

    
 
 

您可能感兴趣的文章:

 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • java命名空间java.net类httpurlconnection的类成员方法: http_not_found定义及介绍
  • java开发知识 iis7站长之家
  • /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found
  • 关于fedora 14 command not found的问题
  • help,please:command not found
  • maemo -sh: sudo: not found 怎么办
  • (菜鸟问题)command not found
  • 悲剧了!!!libQtCore.so.4 not found!!!
  • no devices listed in conf file were found 这个提示
  • 菜菜的问:command not found
  • 命令行输入mysql -uroot ,提示:command not found
  • root.sh: command not found
  • bash :ifconfig:command not found 为什么呢 ?
  • 初次运行服务器APACHE,但用浏览器打开一个HTML后出现FOUND的大字!
  • 请问:我在vware中挂载光驱时,老提示no medium found,这是怎么回事呀,
  • 急:symbol not found
  • command not found ?????
  • 为什么在cygwin 中使用 ldd 出现conmand not found 的提示呢?
  • 求救!!'GLIBC_2.4' not found
  • aix编译问题xlc_r: not found
  • patch : command not found


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3