JRuby:使Java和Ruby成為一家人
一、 引言
Ruby是現(xiàn)在編程界討論得正熱火朝天的一種語言。這種語言功能強大而且易于使用;同時Ruby還緊密綁定到例如Ruby on
Rails等web應(yīng)用程序開發(fā)框架中。另一方面,在過去的十年間,Java正迅速成長為業(yè)界領(lǐng)先的面向?qū)ο蟮能浖_發(fā)語言并且運行于諸多平臺之上。而
JRuby則是一個100%的Ruby編程語言的純Java實現(xiàn)。本文是JRuby的一個入門篇;同時,還會向你展示它是如何結(jié)合Java語言的優(yōu)勢,從
而提供給Java開發(fā)者一個快速而強有力的創(chuàng)建應(yīng)用程序的可選方案的。
二、 Ruby-席卷計算世界的腳本化語言
近幾個月來,在編程領(lǐng)域的幾乎每一個人可能都會耳濡目染Ruby。日益盛行的Ruby on Rails
web開發(fā)框架正在幫助使Ruby成為快速開發(fā)和測試應(yīng)用程序的一門語言。作為一種解釋性的腳本化語言,Ruby提供了快速而容易的面向?qū)ο缶幊碳夹g(shù),同
時還提供了許多非常干凈利索的特征,例如closure,塊和mixins。另外,Ruby還是高度可移植的,可以廣泛運行于Unix/Linux,
Windows以及MacOS平臺之上。要想全面了解Ruby,我建議你去閱讀W.Jason Gilmore的文章。
三、 Java-輝煌的面向?qū)ο笳Z言的十年
Java最早由Sun Microsystems的James
Gosling在上一世紀(jì)九十年代創(chuàng)建。當(dāng)時,Gosling開發(fā)這一語言的主要目的是想提供一種虛擬機(jī)和一種C風(fēng)格的標(biāo)志語言,同時使之具有比C/C+
+更為一致和更為簡單的特征。Java的另一個主要的目標(biāo)是提供一種"編寫一次處處都能運行"(WORA)的理想語言,允許一個程序在一種平臺上開發(fā)而能
夠不經(jīng)任何重編譯即可運行于另一種平臺。這個Java平臺由一個Java運行時刻環(huán)境和Java軟件開發(fā)包(SDK)組成?,F(xiàn)在,Java能夠為從移動設(shè)
備到企業(yè)系統(tǒng)的諸多平臺提供SDK,這分別對應(yīng)于它的JavaSE,EE和ME技術(shù)。在過去的十年間,Java已經(jīng)被廣泛應(yīng)用于移動設(shè)備、無人值守系統(tǒng)、
web應(yīng)用程序、金融系統(tǒng)以及實時系統(tǒng)等眾多開發(fā)領(lǐng)域。
四、 JRuby-Java虛擬機(jī)(JVM)上運行的Ruby
JRuby則是一個100%的Ruby編程語言的純Java實現(xiàn),這種語言在CPL,GPL和LGPL三種開源許可下發(fā)行。它是一個1.8.4
Ruby解釋器,其中提供了大多數(shù)Ruby的內(nèi)置類。JRuby支持從一個Ruby程序中定義Java類并實現(xiàn)與之交互,另外還對Bean腳本化框架實現(xiàn)
支持。在本文成文之時,JRuby的當(dāng)前版本是0.9.1。JRuby使Ruby程序能夠存取Java類,允許它們作為程序內(nèi)使用的一級對象。如今,
JRuby的創(chuàng)始人,Thomas Enebo和Charles Nutter,已經(jīng)受雇于Sun專門研究開發(fā)JRuby。
五、 運行你的第一個JRuby程序
JRuby的發(fā)行中帶有一個tar.gz文件。在本文中,我基于Windows系統(tǒng)并使用JRuby的jruby-bin-0.9.1.tar.gz
二進(jìn)制發(fā)行版本以及Java
SE版本1.5.0_06。在解壓這些發(fā)行文件后,會出現(xiàn)一個jruby-0.9.1文件夾,其中包含的子文件夾有:bin,docs,lib和
samples。注意,你可以添加一個指向這個目錄的JRUBY_HOME環(huán)境變量,然后把%JRUBY_HOME%bin(在UNIX系統(tǒng)上是$
JRUBY_HOMEbin)添加到你的系統(tǒng)路徑下。JRuby發(fā)行版的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
第一行代碼負(fù)責(zé)啟動JRuby的Java支持并且允許一個Ruby程序使用Java類。
該程序定義了一個指向文件"./samples/java2.rb"的java.io.FileReader。然后,它聲明了一個
java.io.BufferedReader用于緩沖經(jīng)由FileReader讀取的數(shù)據(jù)。本文程序從這個文件中讀取所有的代碼并且把它們輸出到控制
臺。下面是使用JRuby運行這個Ruby腳本的輸出結(jié)果:
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>
到現(xiàn)在為止,你已經(jīng)能夠使用JRuby運行一個Ruby腳本;該腳本能夠使用Java類讀取一個文件并且輸出其內(nèi)容。這是JRuby向Ruby用戶展示的一個強有力的概念。
六、 在JRuby中使用Java類(包括命名沖突問題)
現(xiàn)在,既然你已經(jīng)能夠運行一個示例,那么接下來,讓我們來看一下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方法調(diào)用來實現(xiàn):
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來存儲三個字符串并且打印它們。這個程序中有趣的地方在于,它調(diào)
用Ruby的java.util.Set(通過java.util.HashMap.keySet()方法調(diào)用返回)中的each方法。這允許把通過這個
"each"方法返回的結(jié)果鍵傳遞給相應(yīng)的代碼塊,然后該代碼塊使用該鍵取得相應(yīng)的字符串,并且輸出該字符串。
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) }
然而,有可能在Java類和Ruby類之間存在命名沖突問題。其中,字符串的使用就是一個例子;Java中提供了java.util.String,
而Ruby中提供了Kernel::String。為了解決這個命名沖突問題,你可以在包括它時重命名這個類-通過把一個代碼塊傳遞給
include_class方法調(diào)用來實現(xiàn):
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來存儲三個字符串并且打印它們。這個程序中有趣的地方在于,它調(diào)
用Ruby的java.util.Set(通過java.util.HashMap.keySet()方法調(diào)用返回)中的each方法。這允許把通過這個
"each"方法返回的結(jié)果鍵傳遞給相應(yīng)的代碼塊,然后該代碼塊使用該鍵取得相應(yīng)的字符串,并且輸出該字符串。
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) }
然而,有可能在Java類和Ruby類之間存在命名沖突問題。其中,字符串的使用就是一個例子;Java中提供了java.util.String,
而Ruby中提供了Kernel::String。為了解決這個命名沖突問題,你可以在包括它時重命名這個類-通過把一個代碼塊傳遞給
include_class方法調(diào)用來實現(xiàn):
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來存儲三個字符串并且打印它們。這個程序中有趣的地方在于,它調(diào)
用Ruby的java.util.Set(通過java.util.HashMap.keySet()方法調(diào)用返回)中的each方法。這允許把通過這個
"each"方法返回的結(jié)果鍵傳遞給相應(yīng)的代碼塊,然后該代碼塊使用該鍵取得相應(yīng)的字符串,并且輸出該字符串。
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) }
下面是當(dāng)使用JRuby運行它時的輸出結(jié)果:
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));
}
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。