eclipse是一个流行的针对java编程的集成开发环境(ide)。它还可以用作编写其他语言(比如c++和ruby)的环境,合并各种种类工具的框架,以及创建桌面或服务器应用程序的富客户端平台。如今,eclipse开源社区拥有数十个项目,其范围从商务智能到社会网络等各个方面。eclipse同时也是管理这些项目的非赢利性组织的名称。(而且,尽管我相当肯定它并非地板蜡,还是存在eclipse汽车、足球队和口香糖。)
eclipse version 3.2在eclipse callisto 发行历史上具有里程碑的意义:于2006年6月30日同时发布了10个eclipse项目。本文将集中探讨eclipse ide,特别是其java 开发工具 (jdt)。
jdt构成
jdt的历史可以追溯到1996年左右使用smalltalk编写的visual age for java(vaj)。在vaj中,一切内容都会在输入时进行编译,并在内存中完全解析。这种设计的可伸缩性不是很好,难于扩展,重建文件也有一定的困难。
1999年,该ide团队开始开发visual age micro edition(vame)。这个工具完全以java编写,并使用标准widget 工具箱(swt)来实现其用户接口。当时的vame将目标定为嵌入式空间中的开发与应用。为此,它使用了标准的java vm,并把工作区保存在文件系统中。然而,文件和文件夹名称都是一些无法读取的uuid。
与vaj提供的编译器相比,vame的增量式编译器快了近10倍。该模型是基于状态构建的(与目前的eclipse相反,eclipse是基于源代码的)。vame有自己的存储库系统rapier,并且可以使用插件对其进行扩展。
vame实际上并没有在社区中流行开来,但是它包含了大量优秀的思路,开发人员在接下来的eclipse项目中延用了这些思路。2001年,eclipse 1.0发布。它被描述为“一种通用的ide,并不特别针对于什么内容”。一开始,eclipse和jdt都被构建为其他开发工具使用的平台。工作区保存在磁盘上,并对其他工作区开放。eclipse 1.0集成了cvs,而没有使用专用的存储库。
eclipse与其先行者之间有一个重要的区别:它是开源的。其用户社区以爆炸式的速度增长,并可独立维持。eclipse 3.2的大部分新的和改进功能都源自eclipse用户提出的增强要求。自从3.1版本以来,已经有超过30,000个修复和增强的要求得到了解决。由于要把全部这些要求都过一遍需要很长时间,下面我们就重点讲述其中一些对于大多数java开发人员特别重要的要求。
eclipse编译器
jdt更为强大的功能之一即是它内置的增量式java编译器,这个编译器与javac完全兼容。尽管可以让eclipse使用ant和javac,甚至可以让问题标志显示在ide中(此为3.2版本中的新功能),但是eclipse编译器可以提供更好的诊断技术和更快的周转周期。
jdt编译器原本是为vame而编写的,后针对eclipse进行了修改。这个编译器构建在开发人员称之为“编译的3大规则”(模仿了阿西莫夫的机器人3大定律)之上:
- 正确性:编译器不能伤害源程序。
- 高效性:编译器必须快速,除非速度与规则1发生冲突。
- 友好性:编译器必须帮助用户纠正编程错误,只要这类帮助不与规则1和规则2冲突。
正确性:设计java编译器时,不仅必须遵循相应的规范,而且必须领会该规范的“精神”,仅仅考虑正确性是不行的。因此,jdt开发人员多年来辛勤工作,以便与其他编译器的功能保持一致,其中包括sun的编译器。在eclipse 3.2中,仅针对正确性的检查就超过了15,000次单元测试(相比之下,vaj中根本没有进行单元测试)。
高效性:数千个项目和数百万行代码往往是很平常的事情。这意味着要解决很多问题,例如内存使用必须是可预测的并加以分级。eclipse 3.2继续对此进行积极的优化。例如,开发人员可以重写一个流程图以使用位操作,结果位操作的时间消耗从20%降到了4%。
友好性:报告错误是一门艺术。仅仅使用行号还不够。二级错误被最小化。例如,如果一个文件内漏掉了一个分号,它不会影响到与它相关的其他文件。改进后的静态分析功能有助于发现错误模式。另外,eclipse还可以对javadoc进行正确性检查。
就3.2版本来说,eclipse编译器是与java se 6.0兼容的。没错,eclipse支持java 6类和stackmaptable属性(甚至在java 6发布之前)。另外,该编译器还提供大量新的诊断功能,有助于在运行代码之前发现其中的错误。与3.2版本的编译器(提供了45种诊断功能)相比,vaj仅提供了3类诊断功能。最新的一些诊断功能包括对以下内容的检测:
- 使用显然是null的变量。
- 不必要的null检查。
- 对方法参数的偶然赋值。
- 通过让之前的大小写状态失效的方式,切换大小写输入。
- 使用非一般(原始)类型。
- 未使用的标签。
- 不必要的$non-nls$ 标签。
在默认情况下,大多数这些功能都处于关闭状态。当然,还可以使用@suppresswarnings注释把它们设置为关闭状态。
从3.2版本开始,如果想在eclipse外部使用eclipse编译器,您可以单独下载该版本。它的命令行参数与javac兼容,并且下载文件大小仅有1mb左右。既然eclipse编译器是开源的,所以许多其它项目(例如apache tomcat)就可以把它绑定到它们自己的软件中。
编辑
任何开发环境的最基本特征首先体现在编辑器上。您会在这方面花上大部分的时间;因此,编辑器必须是舒适、不唐突且功能强大的。自从emacs以来,每个编辑器都至少包含一些常见源程序语言的基础知识,以便能够提供语法高亮显示功能。jdt使用它的java模型来提供语法高亮显示功能;例如,它十分清楚类与实例变量之间的区别,因此能以不同的颜色来标志它们。它甚至能够根据源码注释来指出您调用的一个方法是否是过时的(或不推荐使用),并且针对这一方法调用绘制一条直线以强调这部分代码值得注意。
在java编辑器中,更有用的命令之一是ctrl-space (内容辅助)。不记得一个对象的方法有哪些或如何拼写一个类名吗?只要按下ctrl-space, eclipse将在任何指定点提供一个有效的可能性列表。eclipse 3.2继续改进这项功能。例如,输入长标识符,例如“longjavaname”时,现在您可以输入“ljn”并且按下ctrl-space, eclipse就会知道您的意思。这称作“camelcase完成”功能。进行类型查找时,它也能发挥作用(ctrl-shift-t)。
您是否厌烦了输入像"stringbuffer buffer = new stringbuffer();"?这样的惯用语。现在,不必再进行这类重复了。在3.2版本中,可以输入:"sb," ctrl-space, space, ctrl-space, " = new ", ctrl-space, "();"来代替。在此,我们使用了16次击键来代替了47次击键。想在一个变量名前加上不同的前缀吗?没问题――只要在第二个ctrl-space之前输入它即可。例如,在3.2版本中,"element root" + ctrl-space完全等价于"element rootelement" (见图1)。
图 1.在3.2版本中内容辅助(ctrl+space)继续得到改进,现在它支持camelcase并可保存已经输入的字符。
下面这项功能更加节省时间。在3.2版本中,ctrl-space将根据使用模式动态地重排它的建议。因此,例如,如果您总是把arraylist实例赋值给list变量,那么arraylist建议将排在第一位,以便您可以更快地选择它。现在,代码完成功能甚至能够工作于javadocs中,因此您可以创建@links或常用引用而不必记住这些长长的名称。
您是否提出过这样的问题:“如果ide足够聪明――能够找出在这一行中存在问题,那么它为什么不能改正这个问题呢?"如今,eclipse加入了一项叫做"quick fix"的功能,可以做到这一点,甚至有过之而无不及。只要把光标放到有问题的代码行上并按下ctrl-1键,那么eclipse将提供有关于修复这个问题的建议。
eclipse的每一个新的发行版本都会加入一些新的快速修复;例如在版本3.2中,如果看到关于使用原始类型的一条警告,只要把光标放到那一行上,然后按下ctrl+1,并且选择一种修复,例如"add type parameters"即可。还有,在3.2版本中,quick fix能够维护同一个文件甚至在多个文件中的许多常见问题,而不必单独处理每一个问题。
我想提到的另一项功能是“重命名类型”。如果您像我一样,经常以类似于类型的方式对变量和方法命名。例如,如果类型为bar,那么很可能有一个变量fbar和一个方法createbar (见图2)。问题是,如果想把bar重命名为另一个名称,那么还要修改大量其他的地方。但是,在3.2版本中,把具有相似名称的变量和方法统一地改变为其他新名称是极其简单的事情。在3.2版本提供的功能中,我最喜欢的就是这种神奇的重命名功能。
图 2.当在eclipse 3.2中重命名一个类型时,同时可以重命名具有类似名称的变量和方法。
运行
在一些ide中,一般要设置一个项目为“主项目”,并且使用一个全局的run命令来运行这个程序。相比之下,eclipse的工作方式有所不同。在eclipse中,有一个启动配置列表,它包含了有关运行、调试或测试代码的所有详细信息,例如命令行参数、类路径、jre版本,等等。在eclipse 3.2中,通过使用过滤和执行环境,管理启动配置变得更为容易。
过滤让您可以根据感兴趣的内容进一步裁减配置列表。执行环境为您提供使用一种通用名称,比如"j2se-1.4",来描述一个java运行时刻的能力。eclipse能够选择满足或超出指定环境要求的jre版本。
您是否曾发现自己在开发期间曾运行过多个测试集?在3.2版本中,可以在同一时刻运行多个测试集,并且可以“回溯”和查看以前的运行历史。eclipse 3.2还支持最新版本的junit(4.0版本)。
团队工作
您是否曾发现自己曾盯着一行代码发愣:是谁加入了这些代码?为什么?eclipse 3.2能显示基于颜色的注释,以便确定当前文件中各部分内容的作者――这是通过读取cvs历史(见图3)而实现的。把鼠标停在一个修改块上将显示开发者的姓名、相应的日期和注释信息。它还会高亮显示在文件其他部分中作过相同改动的代码。
图 3. cvs quick diff注释显示基于颜色的注释(当前文件中各部分内容的作者),在某一部分上停留鼠标将显示该修改版本的细节。
我相信您曾有过这种体会:您调用其他人编写的代码时一切都能顺利工作,直到它们以一种新的版本出现为止。然后,您开始看到一些有关过时的“警告”,更有甚者,竟然出现一些编译错误,直到您修改程序以适应这些修改为止。好了,现在的eclipse 3.2引入了一项非常酷的功能,称为“重构脚本”,可以极大地简化这一过程。
当然,重构仅仅意味着改变源码,而不改变其行为。例如,也许存在拼错的字段,或者一个方法需要一个新的参数。eclipse一直为实现类似修改的自动化提供良好的支持。而且,现在它还为使用者提供帮助。
您所做的每项重构操作都会记入历史。eclipse 3.2让您可以把这些历史写入到外部的脚本文件中,以便日后可以回放。可以把这些脚本保存到cvs中或把它包含到一个jar文件中,这样该jar文件的用户就能够在他们得到一个新版本时“回放”同样的修改动作。这与应用补丁是不同的。补丁只能面向它们所针对的特定源文件操作而使用,而重构脚本却能够针对使用重构api的任意源码文件进行操作。
维护一个不断发展的api以便让他人使用,这是一项相当困难的工作,现在eclipse使得这一工作变得容易多了。重命名一个方法时,eclipse 3.2能够保持旧的方法不变,把它标记为“过时的”,然后对之进行重定向以便调用新的方法,并制作一个重构脚本,以便在调用者导入新的jar文件时自动地转换所有这些调用者。
代码清洁器
一直以来,eclipse都具有一种相当强大的代码格式化功能,以帮助您在整个团队中应用代码格式化标准。3.2版本提供了一个新的“clean up”向导(见图4),进一步加强了这一功能。下面列出这个向导可以选择实现的一些功能:
- 删除不用的导出功能。
- 删除不用的私有方法和构造器。
- 添加缺少@override的@deprecated和注释。
- 添加缺少的$non-nls$标签,或删除不必要的标签。
- 把所有for循环转换为增强的-for循环。
- 把控制语句主体转换为块。
- 删除不必要的强制转换。
- 为serializable和externalizable类添加连续版本id。
clean up向导可以在java文件、软件包或整个项目上运行。
图 4. clean up向导让您可以在整个项目范围内应用一致的标准。
结束语
如今,相对于任何其他语言和平台来说,可供java程序员选择使用的工具相当之多。我也搞不清楚这其中的原因――也许是用户的巨大能量和积极性所致,或者是没有单一的垄断供应商(例如microsoft)将其意愿强加于平台并将其工具直接与平台绑定的结果。无论原因是什么,eclipse都能够与许多备选方案(包括netbeans、idea、jdeveloper和jbuilder)相媲美。随着3.2版本的发行,eclipse在java ide方面有了一次大的飞跃,这将会使所有的java程序员受益,不管您最终选择的是哪一种工具。
参考资料
作者简介 | |
ed burnette 居住在美国北卡罗来纳州的卡里市,是一名专业的开发人员和程序设计者。 |