摘 要:Java領(lǐng)域混合語言編程時代已經(jīng)到來。本文首先回顧靜態(tài)類型語言和動態(tài)類型語言、命令式語言和聲明式語言的基本概念和各自的優(yōu)缺點,然后介紹Java語言的發(fā)展趨勢和基于Java Virture Machine的代表性語言Jython、JRuby、Groovy、Scala和Clojure,最后指出軟件項目的未來在于混合語言編程,Java仍將是JVM生態(tài)系統(tǒng)中的重要組成部分。
關(guān)鍵詞:JVM;Groovy;Scala;Clojure;多語言混合編程
中圖分類號:TP311 文獻標識碼:A
1 引言(Introduction)
Java語言的一個非常重要特點就是平臺無關(guān)性,而使用Java Virtual Machine(JVM,Java虛擬機)是實現(xiàn)這一特點的關(guān)鍵。JVM是一個虛構(gòu)的計算機,它是通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的,因此JVM屏蔽了與具體平臺相關(guān)的信息,使得Java語言編譯程序只需生成在JVM上運行的目標代碼(字節(jié)碼),就可以在多種平臺上不加修改地運行。JVM在執(zhí)行字節(jié)碼時,把字節(jié)碼解釋成具體平臺上的機器指令執(zhí)行,這就是Java能夠“一次編譯,到處運行”的原因。
雖然JVM是為支持Java語言的語義而設(shè)計的,但是這種將編程語言與運行時環(huán)境分開的技術(shù)使得它也可以用作其他語言的目標。在過去幾年間,使用JVM來運行非Java程序的情況成增長趨勢,據(jù)統(tǒng)計有超過200種語言能夠運行在JVM平臺上。有的基于JVM的語言Jython(1997年)和JRuby(2000年)都是從其他已存在的語言移植到JVM中來的,Jython(之前被稱為Jpython)是一個基于JVM的Python語言實現(xiàn),Sun公司資助的JRuby是一個基于JVM的Ruby版本,而全新的基于JVM的語言是Groovy、Scala。Clojure還算不上是JVM的一種新的編程語言,它是一種Lisp方言。
隨著運行在JVM上的程序設(shè)計語言大量增多,大大激發(fā)了多語言編程理念,因為這樣你可以混合使用編程語言并可以選擇最佳匹配,同時還維護著相同的底層字節(jié)碼和類庫。在實際應(yīng)用中,沒有一種語言可以做到完美解決一切問題,每種語言都有自己擅長的方面,而且日趨復雜的軟件需求也使得混合編程的應(yīng)用場景更加頻繁。對于Java程序員來說,技術(shù)單一正面臨著危機,混合編程時代已經(jīng)到來,這是Java程序員必須迎接的挑戰(zhàn)。
本文接下來首先回顧靜態(tài)類型語言和動態(tài)類型語言、命令式語言和聲明式語言的基本概念和各自的優(yōu)缺點,然后介紹Java語言的發(fā)展趨勢和基于JVM的代表性語言Jython、JRuby、Groovy、Scala和Clojure,最后指出軟件項目的未來在于混合語言編程,Java仍將是JVM生態(tài)系統(tǒng)中的重要組成部分。
2 靜態(tài)類型語言和動態(tài)類型語言(Statically typed
language vs. dynamically typed language)
根據(jù)變量的類型是在編譯時確定還是在運行時確定,編程語言可分為靜態(tài)類型語言和動態(tài)類型語言。靜態(tài)類型語言是指在編譯時變量的數(shù)據(jù)類型即可確定的語言,如:Java,C++等等,多數(shù)靜態(tài)類型語言要求在使用變量之前必須聲明數(shù)據(jù)類型(某些具有類型推導能力的現(xiàn)代語言可能會部分減輕這個要求)。與此相反,動態(tài)類型語言是指在運行時確定數(shù)據(jù)類型的語言,變量使用之前不需要類型聲明,通常變量的類型是被賦值的那個值的類型,如:Python和Ruby就是典型動態(tài)類型語言,很多腳本語言vbscript,javascript也是這類語言。
要區(qū)分靜態(tài)和動態(tài)類型語言僅從語法格式上就足夠了,如代碼清單1和代碼清單2所示:
public int add(int x,int y){
return x+y;
}
代碼清單1:靜態(tài)類型語言(Java)
function add(x,y){
return x+y;
}
代碼清單2:動態(tài)類型語言(JavaScript)
靜態(tài)類型語言的主要優(yōu)點在于其結(jié)構(gòu)規(guī)范,便于調(diào)試,方便類型安全,缺點是為此需要寫更多的類型相關(guān)代碼。靜態(tài)類型語言為了達到多態(tài)會采取一些類型鑒別手段,如繼承、接口,而動態(tài)類型語言則不需要。動態(tài)類型語言的優(yōu)點在于不需要寫非常多的類型相關(guān)的代碼,缺點自然就是不方便調(diào)試,命名不規(guī)范,會造成不利于理解等。
3 命令式編程語言和聲明式編程語言(Imperative
programming language vs. declarative
programming language)
根據(jù)編程范式的不同,高級編程語言可分為命令式語言和聲明式語言,兩者的編程方式有很大的差異。
命令式語言是基于動作的語言,以馮諾依曼計算機體系結(jié)構(gòu)為背景。機器語言及匯編語言是最早的命令式語言,在這種語言中,計算機被看作是動作的序列,程序就是用語言提供的操作命令書寫的一個操作序列。用命令式語言編寫程序,就是描述解題過程中每一步,程序的運行過程就是問題的求解過程。命令式語言分為面向過程和面向?qū)ο?,傳統(tǒng)的命令式語言比如Fortran、C和Pascal都是面向過程的,它們主要的程序設(shè)計單元是過程?,F(xiàn)代的命令式語言比如C++、Java和C#則是面向?qū)ο蟮?,它們將對象作為程序的基本單元,將程序和?shù)據(jù)封裝其中,通過對象之間的協(xié)作來解決問題。
聲明式編程與命令式相對立,不同于命令式編程需要用算法明確指出每一步該怎么做,聲明式編程描述目標的性質(zhì),讓計算機明白目標,而非流程,即告訴計算機需要計算“什么(What)”而不是“如何(How)”去計算。聲明式編程是一個大的概念,其下包含一些有名的子編程范式:約束式編程、領(lǐng)域?qū)僬Z言、函數(shù)式編程、邏輯式編程等。例如:數(shù)據(jù)庫查詢語言(SQL,XQuery),正則表達式屬于領(lǐng)域?qū)僬Z言,LISP屬于函數(shù)式編程語言,Prolog屬于邏輯式編程語言。聲明式編程語言通常用作解決人工智能問題和約束滿足問題。endprint
命令式編程通常會讓代碼變得十分冗長,更重要的是由于它提供了過于具體的指令,使得執(zhí)行代碼的基礎(chǔ)設(shè)施(如JVM)沒有太多的發(fā)揮空間,只能老老實實地根據(jù)指令一步步地向目標前進。因為像“執(zhí)行目的”這樣更高層次的信息已經(jīng)丟失了,并行執(zhí)行程序會變得十分困難,因此,編程語言的趨勢之一,便是能讓代碼包含更多的“What”,而不是“How”,這樣執(zhí)行環(huán)境便可以更加聰明地去適應(yīng)當前的執(zhí)行要求,所以聲明式編程自2009年起備受人們的關(guān)注。
4 Java語言的發(fā)展趨勢(The trend of the Java
language)
Java語言集許多語言的優(yōu)點于一身,它的面向?qū)ο筇匦宰尨笮蛙浖こ套兊酶尤菀坠芾?,它的自動垃圾回收機制能有效地管理內(nèi)存和防止內(nèi)存泄露,它的平臺無關(guān)性讓Java在服務(wù)器端軟件領(lǐng)域獲得巨大成功。Sun公司在推出Java時就將其作為開放的技術(shù),得到了廣大軟件開發(fā)商的支持,Java擁有世界上最大的開發(fā)人群和開源生態(tài)系統(tǒng),這是其他語言無法比擬的。
Java語言已經(jīng)證明了它的強大與成功,但是Java并不是盡善盡美的。對Java語言的批評主要集中在三個方面:語言問題、模塊化問題、性能問題。首先是語言問題,Java是靜態(tài)類型語言,屬于命令式編程范式,它的語法與固有范式存在著已知的局限性。Java語言的一個發(fā)展趨勢是在可能的范圍內(nèi)降低語言本身的語法復雜度,從J2SE 5.0中增強的for循環(huán),到Java SE 7中的try-with-resources語句和<>操作符,再到Java SE 8中引入的lambda表達式,Java正在不斷地簡化自身的語法并引入一些重要的現(xiàn)代語法特征,例如函數(shù)式編程中的某些特性。第二是模塊化問題,Java平臺所包含的各種功能不同的類庫是一個統(tǒng)一的整體,在一個程序的運行過程中很多類庫其實是不需要的。模塊化的含義是把Java平臺提供的類庫劃分成不同的相互依賴的模塊,程序根據(jù)需要選擇運行時所依賴的模塊,只有被選擇的模塊才會在運行時被加載。模塊化的實現(xiàn)不僅可以應(yīng)用到Java平臺本身,也可以應(yīng)用到Java應(yīng)用程序的開發(fā)中,OpenJDK中的Jigsaw項目提供了這種模塊化的支持[1]。第三是性能問題,這主要是因為JVM這個中間層次的存在。隨著硬件技術(shù)的發(fā)展,越來越多的硬件平臺采用了多核CPU和多CPU的架構(gòu),Java平臺需要幫助開發(fā)人員更好地充分利用這些資源來提高程序的運行性能。Java SE 7中的fork/join框架是一個高效的任務(wù)執(zhí)行框架。Java SE 8對集合類框架和相關(guān)API做了增強,以支持對批量數(shù)據(jù)進行自動的并行處理。
Java仍然是最受歡迎的編程語言,而且至少在接下來的這幾年里不會改變,原因有很多:首先,許多計算機科學的程序和其他領(lǐng)域的程序是用Java編寫的。第二,Java有一個巨大的穩(wěn)定的代碼庫。第三,有大量的廠商投資、工具、培訓和其他產(chǎn)品,使得無論是供應(yīng)商還是他們的客戶都依賴Java。第四,Java擁有最大的開發(fā)社區(qū)和開源生態(tài)系統(tǒng),當涉及到選擇何種工具、供應(yīng)商和開發(fā)者作為未來的開發(fā)方向時,Java仍然是首選。
5 基于JVM的語言(JVM-hosted languages)
Java面臨的最大的威脅是快速發(fā)展的JVM-hosted語言,如Jython、JRuby、Groovy、Scala和Clojure,這些語言都基于JVM,它們可以與Java語言方便簡單地集成,相比Java都有更加簡明的語法和豐富的表達能力。以Groovy、Scala和Clojure為代表的JVM語言被業(yè)界稱為“JVM三巨頭”,調(diào)查顯示Groovy和Scala兩者都顯示出強勁的商業(yè)應(yīng)用熱度,Clojure的支持絕大部分來自業(yè)余愛好者和lisp黑客,而不是商業(yè)組織[2]。沒有任何一種語言可以徹底地取代另外一種或是所有的語言,它們根據(jù)各自的擅長很好地解決問題。
5.1 Jython
Jython即是Python語言的Java實現(xiàn)。要了解Jython,首先要了解Python。Python支持命令式程序設(shè)計、面向?qū)ο蟪绦蛟O(shè)計、函數(shù)式編程、面向方面的程序設(shè)計、泛型編程多種編程范式。Python開發(fā)者的哲學是“用一種方法,最好只有一種方法來做一件事”,因此Python源代碼具備很好的可讀性,并且能夠支撐大規(guī)模的軟件開發(fā)。Python語言及其眾多的擴展庫所構(gòu)成的開發(fā)環(huán)境十分適合工程技術(shù)、科研人員處理實驗數(shù)據(jù)、制作圖表,甚至開發(fā)科學計算應(yīng)用程序。一些知名大學采用Python教授程序設(shè)計課程,例如卡耐基梅隆大學的編程基礎(chǔ)和麻省理工學院的計算機科學及編程導論就使用Python語言講授。
Jython是用Java編寫,它繼承了Java和Python二者的特性而顯得很獨特,如Jython代碼的可讀性和清晰性,與Java的無縫集成,動態(tài)類型,Java程序員在數(shù)日內(nèi)就能熟悉Jython。
5.2 JRuby
JRuby是Ruby語言的純Java實現(xiàn)(Ruby是用C寫的),它結(jié)合了Ruby簡潔的語法以及Java豐富的類庫,通過JRuby可以在JVM上直接運行Ruby程序,調(diào)用Java的類庫。JRuby無縫地“組合”了Java和Ruby的優(yōu)勢,使我們的開發(fā)效率事半功倍[3]。
Ruby發(fā)明的理念是“你既能進行高效開發(fā)又能享受編程的快樂”,其次是良好的界面設(shè)計,他強調(diào)系統(tǒng)設(shè)計必須注重人性化,而不是一味從機器的角度設(shè)想,遵循上述的理念,Ruby語言通常非常直觀,按照編程人認為它應(yīng)該的方式運行。Ruby是一種有趣的語言,它支持使用多重范式,其中之一是“函數(shù)式范式”,JRuby是完全面向?qū)ο蟮摹?/p>
5.3 Groovy
Groovy是Java平臺上設(shè)計的面向?qū)ο缶幊陶Z言。這門動態(tài)類型語言擁有類似Python、Ruby和Smalltalk的一些特性,可以作為Java平臺的腳本語言使用。Groovy的語法很像Java以至于多數(shù)的Java代碼也是正確的Groovy代碼,這樣了解Java的開發(fā)者可以更快地學習Groovy。Groovy代碼動態(tài)的被編譯器轉(zhuǎn)換成Java字節(jié)碼。由于其運行在JVM上的特性,Groovy可以使用其他Java語言編寫的庫。Groovy的優(yōu)勢在于易用性以及與Java無縫銜接,一些開發(fā)者由于Groovy和Java的無縫集成而使用Groovy[4]。endprint
5.4 Scala
Scala是一種純粹的面向?qū)ο缶幊陶Z言,Scala中的每個值包括基本數(shù)據(jù)類型都是對象,連函數(shù)也是對象。Scala包含若干函數(shù)式語言的關(guān)鍵概念,把函數(shù)式和面向?qū)ο蟮木幊趟枷牒芎玫亟y(tǒng)一到了一種語言里。Scala可以與Java互操作,可以訪問現(xiàn)存的數(shù)之不盡的Java類庫,這使得Scala成為Java程序員解決某些問題的另一種選擇。Scala把Erlang風格的基于actor的并發(fā)帶進了JVM,開發(fā)者現(xiàn)在可以利用Scala的actor模型在JVM上設(shè)計具伸縮性的并發(fā)應(yīng)用程序,它會自動獲得多核處理器帶來的優(yōu)勢,而不必依照復雜的Java線程模型來編寫程序。因此與Groovy相比,Scala的優(yōu)勢在于性能和一些高級特性[5]。
5.5 Clojure
Clojure給JVM帶來了Lisp。Lisp是基于λ演算的函數(shù)式編程語言,以表達性和功能強大著稱,但人們通常認為它不太適合應(yīng)用于一般情況,Clojure的出現(xiàn)徹底改變了這一現(xiàn)狀,它是一種運行在Java平臺上的Lisp方言,在任何具備JVM的地方都可以利用Lisp的強大功能。Clojure不是面向?qū)ο蟮?,但提供了很多你想從OO中得到的東西,如封裝(通過名字空間、私有定義和閉包)、強大的多態(tài)(multimethods)、函數(shù)重用比繼承更勝一籌。同時,Clojure可以無縫地與Java進行交互操作,因此,Java開發(fā)團隊學習Clojure具有優(yōu)勢。Clojure還把函數(shù)式編程語言引入JVM,使Clojure成為一種進行并行、并發(fā)編程的完美語言,支持現(xiàn)在的多核、多CPU以及分布式計算。
6 結(jié)論(Conclusion)
我們究竟需要什么樣的編程語言?企業(yè)級項目和Web項目需要怎樣的語言?一般而言有以下要求:可伸縮性、可移植性、并行編程、高性能、DSL(領(lǐng)域?qū)僬Z言)的實現(xiàn),還有對于低風險的要求,如與舊項目的兼容性,舊項目遷移的成本,開發(fā)工具的支持,開發(fā)團隊對語言的熟悉情況,以及語言開發(fā)團隊的穩(wěn)定性等等。而具體到每一位開發(fā)者頭上情況變得更加復雜。他們可能想要:動態(tài)的、靜態(tài)的、強類型的、函數(shù)式的、富有表達力的、面向?qū)ο蟮?、容易學習的(在有Java或其他語言開發(fā)經(jīng)驗的基礎(chǔ)上)、快捷的、模塊化的、有強大的類庫、有好用的框架、有合適的IDE、有活躍的社區(qū)等等。某些語言可能滿足上述條件中的若干條,但是沒有任何一種語言能夠滿足所有條件。同時,一個項目的不同層面的需求也是不同的,比如,廣受歡迎的社交網(wǎng)絡(luò)及微博網(wǎng)站Twitter,表層是Ruby on Rails,底層是Scala;著名的在線學習網(wǎng)站Coursera把Scala作為服務(wù)器語言使用。
綜上所述,軟件項目的未來在于混合語言編程,而Java仍將是JVM生態(tài)系統(tǒng)中的重要組成部分。
參考文獻(References)
[1] OpenJdk Project Jigsaw [EB/OL].http:// openjdk.java.net/
projects/jigsaw/
[2] The Big Three-Scala, Clojure and Groovy [EB/OL].http://
thecodegeneral.wordpress.com/2012/03/04/the-big-three-
jvm-languages/.
[3] JRuby Homepage [EB/OL].http://www.jruby.org/.
[4] Groovy Homepage [EB/OL].http://groovy.codehaus.org/.
[5] Scala website [EB/OL].http://www.scala-lang.org/.
作者簡介:
錢宇虹(1967-),女,碩士,副教授.研究領(lǐng)域:軟件開發(fā)與應(yīng)
用,軟件工程,軟件測試技術(shù).endprint