动态网站制作指南 [  QQ表情  ]
[ 投票调查 ]
[ 企业邮箱 ]
[ 网站空间 ]
网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
ASP源码 | .Net源码 | PHP源码 | JSP源码 | JAVA源码 | CGI源码 | VB源码 | C++源码 | Delphi源码 | PB源码 | VF源码 | 汇编 | 服务器
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
文章搜索服务
邮件订阅
输入你的邮件地址,
你将不会错过任何关于:
[ Java教程 ]的信息

本月文章推荐
.使用displaytag使列名显示中文的.
.利用Java Swing 实现游戏开发.
.再论Java Swing线程.
.Eclipse3.1中体验J2SE5.0之泛型(.
.JBuilder2005单元测试之捆绑多个.
.封装JNDI操作LDAP服务器的工具类.
.关掉那可恶的Dos窗口.
.java高级编程:基于JNDI的应用开.
.java性能优化-之一.
.Sun的Java学习之旅.
.javaBean与EJB区别.
.破除java神话之原子操作都是线程.
.精确的浮点数运算(实际应用中经.
.实例:用Java的加密机制来保护你.
.再谈通过 Java 执行 POST 操作.
.经典J2EE开发工具-IBMEclipse简.
.Java Learning Path(二)、书籍.
.Java中this的使用.
.Spring AOP在DWR安全上的应.
.工作流引擎的三种定位及其取舍.

避免使用空指针作为标志以防止出现异常

发表日期:2008-1-5 |



  避免使用空指针作为标志以防止出现异常

Eric E. Allen
软件工程师,Cycorp, Inc.

为开发健壮的程序,我们经常用空指针代替异常情况,但这实际上却把控制流限制在方法调用和返回的普通方式,同时也隐藏了异常情况发生的迹象。在这篇专栏里,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 语言的泛型运行时类型的一种扩展。
上一篇:编程修养 人气:718
下一篇:比较完善的用JAVA解压ZIP 人气:1797
浏览全部Java的内容 Dreamweaver插件下载 常用网页广告代码全集
  最新网站源码 最新软件下载
2008-12-2 OpenPNE中文 v2.12.5 for win 中
2008-12-2 谷秋精品课程软件课程版 v2.3
2008-12-2 晴天电影系统(带一键迅雷/自定义
2008-12-2 QQip138闪字程序
2008-12-2 SmartWeb企业智能建站系统 v1.0.2
2008-12-2 梦想不死个人主页 v2009
2008-12-2 开良ASP小偷程序生成器 v1.1
2008-12-2 toolxp.cnalexa世界排名查询 php
2008-12-2 腾讯留言板 v1.3
2008-11-29 Tencent Traveler 4.4
2008-11-29 龙卷风网络收音机 v3.0.0.0
2008-11-29 Intel Chipset Software Install
2008-11-29 TweakVI 1.0 Build 1100
2008-11-29 Opera 9.62 Build 10469
2008-11-29 MPlayer WW编译版 SVN-r28044(20
2008-11-29 NetTools网络工具v1.0.0破解版
2008-11-29 3DGallery三维体验1.1破解版
2008-11-29 SecretBook保密本v1.0破解版
  发表评论
姓 名: 验证码:
内 容:
站长工具:网站收录查询 | Google PR查询 | ALEXA排名查询 | CSS在线编辑器 | OPEN参数生成器 | 弹出式窗口代码产生器 | 密码登录生成器 | 在线按钮生成器 | Meta标签生成器 | 多色彩特效字代码生成器 | 网页代码调试器 | 在线FTP登陆 | Flash取色器 | 配色代码对照表 | 配色辞典 | CSS生成器 | 广告代码 | 框架网页代码生成器 | js/vbs加密 | md5加密 | 进制转换 | UTF-8 转换工具 | 在线调色板 | Html转换js | Html转换asp | Html转换php | Html转换perl
实用工具:汉字翻译拼音 | 拼音字典 | 符号对照表 | 个税计算 | 实时汇率查询换算 | 经典小工具 | 汉字简繁转换 | 普通单位换算 | 公制单位换算 | 生辰老黄历 | 国内电话区号 | 国家代码与域名缩写 | 文字加密解密 | 元素周期表 | 健康查询 | 世界时间 | 万年历 | 二十四节气 | 汉字横竖排版 | 手机号码查询 | 计算器 | ip搜索
业务联系 | 广告刊登 | 频道合作 | 投稿荐稿 | 联系方式 | 加入收藏 | RSS订阅
Copyright © 2000-2009 www.knowsky.com All rights reserved | 沪ICP备05001343号
ホームページ制作 不動産検索システム 求人情報
防水工事·改修工事 フットサル大会 探偵
SEO対策 中国語教室 ホームページ作成