51CTO编者导言:本文最初撰写于06年,作者Dominic Da Silva是SilvaSoft软件咨询公司的总裁。06年正是Ruby在英文开发界开始广泛流行的时候,而JRuby则刚刚出现不久,引来很多开发者的关注。三年多过去了,文中提到的很多情况已经有了变化,但JRuby的发展势头仍然很好,而且可能会成为Ruby进军企业级开发的重要因素之一。让我们来回顾一下这篇经典的JRuby入门吧。
一、JRuby入门引言
Ruby是现在编程界讨论得正热火朝天的一种语言。这种语言功能强大而且易于使用;同时Ruby还紧密绑定到例如Ruby on Rails等web应用程序开发框架中。另一方面,在过去的十年间,Java正迅速成长为业界领先的面向对象的软件开发语言并且运行于诸多平台之上。而JRuby则是一个100%的Ruby编程语言的纯Java实现。本文是JRuby的一个入门篇;同时,还会向你展示它是如何结合Java语言的优势,从而提供给Java开发者一个快速而强有力的创建应用程序的可选方案的。
二、Ruby-席卷计算世界的脚本化语言
近几个月来,在编程领域的几乎每一个人可能都会耳濡目染Ruby。日益盛行的Ruby on Rails web开发框架正在帮助使Ruby成为快速开发和测试应用程序的一门语言。作为一种解释性的脚本化语言,Ruby提供了快速而容易的面向对象编程技术,同时还提供了许多非常干净利索的特征,例如closure,块和mixins。
另外,Ruby还是高度可移植的,可以广泛运行于Unix/Linux,Windows以及MacOS平台之上。要想全面了解Ruby,我建议你去阅读W.Jason Gilmore的文章。
三、Java-辉煌的面向对象语言的十年
Java最早由Sun Microsystems的James Gosling在上一世纪九十年代创建。当时,Gosling开发这一语言的主要目的是想提供一种虚拟机和一种C风格的标志语言,同时使之具有比C/C++更为一致和更为简单的特征。Java的另一个主要的目标是提供一种“编写一次处处都能运行”(WORA)的理想语言,允许一个程序在一种平台上开发而能够不经任何重编译即可运行于另一种平台。这个Java平台由一个Java运行时刻环境和Java软件开发包(SDK)组成。现在,Java能够为从移动设备到企业系统的诸多平台提供SDK,这分别对应于它的JavaSE,EE和ME技术。在过去的十年间,Java已经被广泛应用于移动设备、无人值守系统、web应用程序、金融系统以及实时系统等众多开发领域。
四、JRuby-Java虚拟机(JVM)上运行的Ruby
JRuby则是一个100%的Ruby编程语言的纯Java实现,这种语言在CPL,GPL和LGPL三种开源许可下发行。它是一个1.8.4 Ruby解释器,其中提供了大多数Ruby的内置类。JRuby支持从一个Ruby程序中定义Java类并实现与之交互,另外还对Bean脚本化框架实现支持。在本文成文之时,JRuby的当前版本是0.9.1。JRuby使Ruby程序能够存取Java类,允许它们作为程序内使用的一级对象。如今,JRuby的创始人,Thomas Enebo和Charles Nutter,已经受雇于Sun专门研究开发JRuby(51CTO编者注:如今Sun将被甲骨文收购,而JRuby核心人员觉得Sun前途不明,已经跳槽到了Ruby on Rails云服务托管公司Engine Yard,其中也包括Thomas Enebo和Charles Nutter这两位。不过对于JRuby而言这也许会是个不错的发展势头)。
五、JRuby入门:运行你的***个JRuby程序
JRuby的发行中带有一个tar.gz文件。在本文中,我基于Windows系统并使用JRuby的jruby-bin-0.9.1.tar.gz二进制发行版本以及Java SE版本1.5.0_06。在解压这些发行文件后,会出现一个jruby-0.9.1文件夹,其中包含的子文件夹有:bin,docs,lib和samples。注意,你可以添加一个指向这个目录的JRUBY_HOME环境变量,然后把%JRUBY_HOME%bin(在UNIX系统上是$JRUBY_HOMEbin)添加到你的系统路径下。JRuby发行版的bin目录中包含一个jruby.bat文件,它用于运行JRuby解释器程序。从命令行下运行“jruby -version”可以测试JRuby是否正确工作:
- C:JRubyjruby-0.9.1>jruby -version ruby 1.8.5 (0) [java]
在上面的samples目录中,你可以找到一些展示JRuby功能的示例Ruby程序。作为***个示例,你可以看一下下面这个java2.rb示例。这个示例包含了下列Ruby代码:
- require "java"
- filename = "./samples/java2.rb"
- fr = java.io.FileReader.new filename
- br = java.io.BufferedReader.new fr
- s = br.readLine
- print "------ ", filename, "------n"
- while s
- puts s.to_s
- s = br.readLine
- end
- print "------ ", filename, " end ------n";
- br.close
***行代码负责启动JRuby的Java支持并且允许一个Ruby程序使用Java类。
该程序定义了一个指向文件“./samples/java2.rb”的java.io.FileReader。然后,它声明了一个java.io.BufferedReader用于缓冲经由FileReader读取的数据。本文程序从这个文件中读取所有的代码并且把它们输出到控制台。下面是使用JRuby运行这个Ruby脚本的输出结果:
- C:JRubyjruby-0.9.1>jruby .samplesjava2.rb
- ------ ./samples/java2.rb------
- require "java"
- filename = "./samples/java2.rb"
- fr = java.io.FileReader.new filename
- br = java.io.BufferedReader.new fr
- s = br.readLine
- print "------ ", filename, "------n"
- while s
- puts s.to_s
- s = br.readLine
- end
- print "------ ", filename, " end ------n";
- br.close
- ------ ./samples/java2.rb end ------
- C:JRubyjruby-0.9.1>
到现在为止,你已经能够使用JRuby运行一个Ruby脚本;该脚本能够使用Java类读取一个文件并且输出其内容。这是JRuby向Ruby用户展示的一个强有力的概念。
#p#
六、在JRuby中使用Java类(包括命名冲突问题)
现在,既然你已经能够运行一个示例,那么接下来,让我们来看一下JRuby是如何允许在Ruby程序中使用Java类的。JRuby提供的最重要的方法是Kernel#include_class方法。这个方法允许Ruby按如下方式使用Java类:
- require "java"
- # Include Java's FileReader
- include_class "java.io.FileReader"
- filename = "./samples/java2.rb"
- fr = FileReader.new filename
然而,有可能在Java类和Ruby类之间存在命名冲突问题。其中,字符串的使用就是一个例子;Java中提供了java.util.String,而Ruby中提供了Kernel::String。为了解决这个命名冲突问题,你可以在包括它时重命名这个类-通过把一个代码块传递给include_class方法调用来实现:
- require "java"
- # Include Java's String as JString
- include_class("java.lang.String") { |package, name| "J" + name }
- s = JString.new("Hello World from JRuby!")
- puts s
通过定义一个包括Java类定义的Ruby模块,你还能够避免这个命名冲突:
- require "java"
- module JavaLang
- include_package "java.lang"
- end
- s = JavaLang::String.new("Hello World from JRuby!")
- puts s
下面提供了一个示例程序,javaHello.rb,它使用Java的HashMap来存储三个字符串并且打印它们。这个程序中有趣的地方在于,它调用Ruby的java.util.Set(通过java.util.HashMap.keySet()方法调用返回)中的each方法。这允许把通过这个“each”方法返回的结果键传递给相应的代码块,然后该代码块使用该键取得相应的字符串,并且输出该字符串。
- require "java"
- module JavaLang
- include_package "java.lang"
- end
- include_class("java.util.HashMap") { |pkg, name| "J" + name }
- s = JavaLang::StringBuffer.new("Hello Java World")
- puts s.append(", I love JRuby")
- m = JHashMap.new()
- m.put("java", "Java")
- m.put("ruby", "Ruby")
- m.put("jruby", "JRuby")
- puts m
- m.keySet().each { |key| puts m.get(key) }
下面是当使用JRuby运行它时的输出结果:
- C:\JRuby>jruby javaHello.rb
- Hello Java World, I love JRuby
- {java=Java, ruby=Ruby, jruby=JRuby}
- Java
- Ruby
- JRuby
- C:\JRuby>
一个完全使用Java编写的类似上面的程序看起来如下所示:
- StringBuffer s = new StringBuffer("Hello Java World");
- s.append(", I love JRuby");
- HashMap<String> m = new HashMap<String>();
- m.put("java", "Java")
- m.put("ruby", "Ruby")
- m.put("jruby", "JRuby")
- for (String key: m.keySet()) {
- println(m.get(key));
- }
七、在JRuby中使用Swing
Swing是一个GUI框架,它允许开发者使用Java语言创建图形化应用程序。下面是一个示例程序,javaSwingHello.rb,它使用Java的Swing来打印一个消息:
- require 'java'
- include_class "javax.swing.JFrame"
- include_class "javax.swing.JLabel"
- frame = JFrame.new()
- jlabel = JLabel.new("Hello from JRuby with Swing")
- frame.getContentPane().add(jlabel)
- # frame.content_pane.add(label)
- frame.pack()
- frame.setVisible(true)
- frame.visible = true
从命令行如下运行这个程序:
- C:\JRuby>jruby javaSwingHello.rb
一个带有文本“Hello from JRuby with Swing”的新窗口将会出现:
八、 结论
本文仅提供一个JRuby语言的简介。JRuby允许现有Java开发者充分利用Ruby提供的强有力和易于使用的编程特点,而Ruby开发者将能够自由使用庞大的曾使Java广泛地应用于各个软件开发领域的Java库来进行开发。在归于Sun麾下之后(51CTO编者注:可能很快就会归甲骨文所有),JRuby的发展前途一定会更加光明。各位读者不妨花一点时间进一步研究一下JRuby,挖掘一下这个工具到底蕴含着多大的能量。
【编辑推荐】