跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

诊断 Java 代码: Repl 提供交互式评价

有效地对软件进行交互式诊断的技术和工具

Eric E. Allen (eallen@cs.rice.edu), 博士研究生, Java 编程语言小组,Rice 大学
Eric Allen 从 Cornell 大学获得计算机科学和数学的学士学位,也是 Rice 大学 Java 编程语言小组的 PhD 研究生。在回 Rice 完成他的学位学习前,Eric 是 Cycorp 公司的主要 Java 软件开发者。他还在 JavaWorld 上主持了一个“Java 初学者”讨论论坛。他的研究涉及源代码和字节码级别上的 Java 语言语义模型和静态分析工具的开发。Eric 是针对 NextGen 编程语言的 Rice 的实验编译器的主要开发者,NextGen 编程语言是 Java 语言添加了一些语言功能的扩展,他还是 DrJava — 一个为初学者设计的开放源代码的 Java IDE — 的项目经理。请通过 eallen@cs.rice.edu与 Eric 联系。

简介: 通常,在运行 Java 程序时,必须使用 String[] 输入参数将参数传入,从 main() 方法运行程序。但是如果程序仍在调试中,那么,这可能会成为一项繁重的任务。本月,Eric Allen 讨论对程序中的表达式和语句进行交互式评价的优点,并且提供几个帮助您处理这一任务的 Java repl(“read-eval-print-loop”工具,“读取-评价-打印-循环”工具)。他还讨论交互式评价如何帮助构建 GUI 和探索新的 API。阅读本文后,您将理解在预调试(pre-debugged)程序中交互地诊断小错误的做法及原因,您将能够使用一些 Java 工具来方便您的工作。请单击本文顶部或底部的 讨论讨论论坛与作者及其他读者共享关于本文的心得。

发布日期: 2002 年 3 月 06 日
级别: 初级
访问情况 : 1181 次浏览
评论: 


多数程序都包含很多方法,这些方法分布在为数众多的类中。毫无疑问,从程序的 main 入口点测试所有这些方法,即使不是不可能的,也是很困难的。

这就是单元测试之所以有用的原因。许多程序员和软件设计人员(包括我自己)强调单元测试在编写健壮的的软件时是有用的。但是如果您想能够以一种交互性更好的方式访问程序中的各种元素时,则可能要折衷一下。

当确实要这样做时,为每个结果编写、编译并运行新的单元测试就会很快变成一件繁重的事情。我发现,当不能预知给予特定输入后程序将表现出什么行为时(例如:在 AI 程序中可能就会出现这种情况),尤其如此。

那么,该怎么办呢?

不要为小改动着急

为了作一个类比,请考虑用通常情况下进行编译的语言(例如:Java 或 C++)编程和用在更多情况下进行解释的语言(Python 或 Scheme)编程之间的差异。

在编译型语言中,每个编写/测试/调试循环都必须包含编译这一额外的步骤,这可能是一个单调乏味的经历,尤其是对于一些小改动而言。这可能会使我们得出结论说,解释型语言更流畅,因而也更易于修改。(这种灵活性是有代价的:解释型语言通常更少对代码执行静态检查,例如类型检查。)

正如有时候我们可能想对程序作个改动,但不必经历重编译的麻烦一样,我们也可能想检查程序中的一些元素,但不必例行公事般在套件中添加一个新的单元测试。当确实想这样做时,拥有传统上称为“读取-评价-打印-循环”(即 repl)的工具可能会有所帮助。

repl是一个基于文本的工具,它以表达式作为输入,在特定程序的上下文中进行评端,然后显示结果。接着,它等待获得另一个表达式作为输入,然后重复这些操作。这样的工具源于类似 Lisp 的语言,但它们也能在更新的语言(例如:Python)中使用。


repl 在 Java 编程中的好处

这样的工具并非仅仅在这些语言中是有用的。Java 程序员也可以从使用 repl 中获得好处,不只是调试方面,在其它方面也可以。

构建 GUI

当组装一个 GUI 时,有许多组件需要布置和连接。当构造 GUI 时,您肯定会碰到以下这些事情:

  • 组件之间将以不可见的方式相互作用。
  • 在运行 GUI 之前写出其所有代码是相当费时的。
  • 一旦您看到了 GUI 的实际视觉效果,不可避免地,您将会想更改 GUI 的某些方面。

这个问题的一种常见的“解决方案”是使用图形化的 GUI 构建工具,例如那些包含在 JBuilder、Forte 和其它 IDE 中的 GUI 构建工具。我个人不喜欢这种办法 ― 您很难知道这个工具会给您生成什么样的 Java 代码,您也不可能在修改所生成的代码时不冒丧失与 GUI 构建工具的兼容性的风险(事实上,有些 IDE 强行禁止您修改机器生成代码的任何部分)。

此外,许多这类 GUI 构建工具在生成 Java 代码时都使用专用 GUI 库,因而限制了 GUI 的兼容性。

我发现使用 repl 来构建 GUI 要容易得多。我完全可以交互地定义每一个 GUI 组件,然后依次显示它。我能够立刻修正任何不喜欢的东西。然后,我可以与之交互并将这些组件粘贴到程序中。

探索新 API

使用 Java 语言编程最大的优点之一是,有数量庞大的 API 可以使用,它们可以与一切事物 ― 从数据库到 Web 服务到电视 ― 对接。不过需要花些时间学习 API 的语义。

通常,Javadocs 不会对 API 的行为的每个方面都作出明确说明。对付这种窘境的办法是直接测试 API,使用 repl 可以使测试快得多 ― 只要输入一个方法调用看看其结果就行了!

一个额外的好处是,使用 repl 测试 API 还强化了大多数程序员的主要行为 ― 我们倾向于在实践中取得最好的学习效果。

一个新的 Java IDE

在 Rice 大学的 JavaPLT 实验室(由 Robert Cartwright 教授领导),我们最近发布了 DrJava,一个新的、开放源代码的、用于 Java 语言的 GPL'd 开发环境,它包含了 DynamicJava repl 的一个洁净(cleaned-up)版本作为内置组件。我说“洁净”是因为我们已经隐藏了前面所描述的 DynamicJava 的某些更随意的功能。

.DrJava 项目是一个极端编程项目,目的是开发供计算机科学低年级大学生教学之用的免费的、轻量级的 Java IDE。尽管这个 IDE 是为大学生设计的,但它的快速开发功能对所有级别的开发者都是有用的。DrJava 背后的理念是利用程序员的语言知识来提供强大的开发工具,这与某些尽力把程序员和实际代码隔离开来的 IDE 不同。

这个 IDE 的一些优异特征包括对注释和圆括号匹配的极其精确(比 Emacs 更精确)的突出显示,以及可单击的编译器错误的源代码突出显示。其界面包含几个可单击的选项卡:

  • Interactions 选项卡允许您与 DynamicJava repl 交互,创建新编译过的类的实例,测试新编译过的类。
  • Compiler Errors 选项卡允许您单击各种编译器错误,将光标移到编辑面板中出错的源代码的位置。
  • Console 选项卡显示所有发送到 System.outSystem.err 的消息。

(这里是 DrJava 的一个 屏幕截图。)


我们对这个 IDE 的经验是,交互作用窗格允许程序员容易地执行复杂的开发和调试任务。跟在其它语言中所表明的一样,源代码编辑器和 repl 的结合构成强大的工具。


Java 编程中可用的 repl

那么,如果 repl 有这么多优点,下一个问题显然是 Java 语言可以使用哪些 repl?

Jython

Jython(以前的名称是 JPython)是 Python 的 Java 编程语言实现(包含一个 repl)(经认证,是 100% 纯 Java 的)。实际上,它把 Python 编译成(有点复杂)Java 源代码或直接编译成字节码。

本着 Python 的精神,人们尝试了各种办法以提供 Java 和 Jython 之间的无缝互操作性。Jython 让您可以访问所有的 Java 标准库,就好像您是自然地使用 Java 语言进行编程一样,您也可以访问现有的 Java 类文件。所以您不仅可以将 repl 用来与标准库一起工作,还可以与已经编译成字节码的您自己的 Java(或 Jython)类一起工作。

使用 Jython repl 时的一个重要注意事项是您在写 Python 表达式,而不是 Java 表达式。其积极的一面是您得到了 Python 在句法方面简明而又优美的优点。

例如,假如我想构造一个新的散列表,这个表将 a 映射到 1、 b 映射到 2, c 映射到 3。使用 Jython 我所要写的只是:

>>> h = {'a':1, 'b':2, 'c':3}

解释器在每一个新的输入行前显示 >>>

当探索新的 GUI 设计时,Jython 句法也有很多优点。举个例子来说,可以将 GUI 元素的各个域指定为构造函数的关键字参数,就像这样:

>>> from javax.swing import *
>>> f = JFrame(visible=1)

这个示例说明了 Jython 和 Java 语言的其它一些差异:

  • 导入语句的句法有很大不同。
  • 整型被用来取代了布尔型(1 是真,0 是假)。

这里是另一个示例,示例中 Jython 代码为您节省了一些输入,给 GUI 元素添加了动作侦听器(action listener)。通常,这样的侦听器通过使用命令模式(Command Pattern)被指定为匿名内部类的实例。在 Python(和其它许多“脚本”语言)中,这样的命令可以通过使用交互式函数定义更简洁地加以指定。例如,让我们在上述的交互式会话的基础上给 JButton 添加一个简单的动作侦听器:

>>> def listener(event):
...   print 'thank you'
>>>

这是 Jython 中的函数定义的一个示例。为了让我们知道它什么时候需要一个语句以便继续进行,解释器在下一行打印省略号(代替脱字符)。这个函数只需要一个参数,并会将“thank you”打印到标准输出。我们可以将它用作动作侦听器,如下:

>>> panel = JPanel()
>>> panel.add(JButton('press me', actionPerformed=listener))
>>> f.getContentPane().add(panel)
>>> f.pack()

现在,我们将有一个显示在屏幕上的窗口,这个窗口有一个标有“press me”的按钮,按下这个按钮后将打印“thank you”到标准输出。想像一下,如果使用 Java 代码的话,这将需要多少语句啊。

当然,缺点也是有的。例如:

  • 您失去了静态类型检查(尽管按理说静态检查在 repl 中没有多少价值)。
  • 因为您输入到 repl 中的表达式不是 Java 代码,所以您无法在转换它们之前将表达式从 repl 中复制和粘贴到您的程序中。
  • 当与 Java 代码一起使用 Jython 时,您得承担在脑海中同时处理两种语言的额外脑力负担(尽管有些人认为这样做很好玩)。

DynamicJava

Java 可以使用的另一个 repl 是 DynamicJava,一个真正基于 Java(呃,基本上是对的)的开放源代码的工具,它有一些不同之处:

  • repl 语言允许您不必在声明变量时指定变量的静态类型。
  • 您不必在语句末尾添加一个分号。解释器也会返回(随意地) null 作为语句的评价结果。(如果语句根本不返回值,情况会好得多。)
  • 不限制您从 repl 内访问对象的私有字段。

对于初级 Java 程序员,这些不同之处是很重要的,因为它们可能会使他们感到很迷惑。更有经验的程序员可能会乐于见到其中一些宽松的约束。无论如何,DynamicJava 都是一个健壮的、非常有用的软件产品(而且它是免费的,这是有帮助的)。


repl 总结

希望本部分已经指出并演示了一种主要工具,它能让您交互地对 Java 程序中的表达式和语句进行评价,而不陷入重编译的泥沼 ― 这种工具就是“读取-评价-打印-循环”即 repl 工具。我们还演示了 repl 如何体现它在构建 GUI 中的重要性,或者当您只是想快速地检查大量可以使用的 Java API 时,它又是如何体现它的重要性的。


参考资料

关于作者

Eric Allen 从 Cornell 大学获得计算机科学和数学的学士学位,也是 Rice 大学 Java 编程语言小组的 PhD 研究生。在回 Rice 完成他的学位学习前,Eric 是 Cycorp 公司的主要 Java 软件开发者。他还在 JavaWorld 上主持了一个“Java 初学者”讨论论坛。他的研究涉及源代码和字节码级别上的 Java 语言语义模型和静态分析工具的开发。Eric 是针对 NextGen 编程语言的 Rice 的实验编译器的主要开发者,NextGen 编程语言是 Java 语言添加了一些语言功能的扩展,他还是 DrJava — 一个为初学者设计的开放源代码的 Java IDE — 的项目经理。请通过 eallen@cs.rice.edu与 Eric 联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=54697
ArticleTitle=诊断 Java 代码: Repl 提供交互式评价
publish-date=03062002
author1-email=eallen@cs.rice.edu
author1-email-cc=eallen@cs.rice.edu

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。