新聞中心
Java所獲得的巨大成功證明了這種設(shè)計(jì)方式是正確的,但如果這依然是當(dāng)今Java的重要目標(biāo)的話,那么其結(jié)果就是語言的演進(jìn)將變得非常緩慢。除此以外,Java是一門成熟、使用廣泛的語言這個(gè)事實(shí)也將導(dǎo)致其演進(jìn)過程充滿了困難。

10年積累的成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有連云港免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
一方面,添加到語言中的每個(gè)特性都可能在一定程度上造成不可預(yù)料的結(jié)果,這么做會疏遠(yuǎn)那些已經(jīng)使用了該語言的開發(fā)者。另一方面,本身很***的特性可能在同語言中的其他特性進(jìn)行交互時(shí)產(chǎn)生不可預(yù)料的結(jié)果。更糟的是,一旦增加了某個(gè)語言特性,幾乎就不可能再將其移除了,即便是該特性會對整個(gè)語言產(chǎn)生不利影響也沒辦法。為了證明某個(gè)新特性是正確的,語言設(shè)計(jì)者必須確信從長遠(yuǎn)來看,該特性會給語言帶來好處,而不是短期效益或是針對某個(gè)問題的快速解決方案,之后就變得可有可無了。
為了降低風(fēng)險(xiǎn),語言設(shè)計(jì)者通常都會創(chuàng)建單獨(dú)的一種語言或是分支來進(jìn)行試驗(yàn),比如Pizza語言就是在實(shí)現(xiàn)前用來測試Java泛型的。這種方式的問題在于試驗(yàn)的參與者非常小眾并且都是自己想?yún)⑴c進(jìn)來的;顯然他們對語言特性很感興趣,很多人都是學(xué)者或研究員。但是,在普通的程序員開始使用這些特性時(shí),那些學(xué)者或是研究員認(rèn)為很棒的特性可能會變得很糟。
為了直觀感受一下這種情況,請考慮關(guān)于Java 7閉包特性的激烈爭論。一段時(shí)間以來,有人在提案中給出了閉包的實(shí)現(xiàn),但最終卻還是沒有達(dá)成共識。隨后,Sun決定不打算在JDK 7中添加完整的閉包支持。這時(shí)爭論的焦點(diǎn)轉(zhuǎn)向?yàn)镴ava是否變得越來越復(fù)雜了,在Java 5中添加泛型(尤其是通配符語法)時(shí)就已經(jīng)出現(xiàn)了這種爭論;在Java已經(jīng)通過匿名內(nèi)部類部分實(shí)現(xiàn)該功能的情況下,完整的閉包支持是否是正確的呢。需要完 整閉包支持的兩個(gè)重要場景是簡化fork/join API(添加到了JDK 7中以改進(jìn)多核編程)的使用以及輔助資源的清理。Josh Bloch的ARM block提案(期望通過Project Coin加入到JDK 7中)就第二個(gè)問題給出了另一種解決方案。Cliff Click博士在面向Java的可擴(kuò)展、非阻塞編程風(fēng)格的研究中給出了關(guān)于fork/join的另一種方案,隨著處理器核心數(shù)的不斷增 加,這種方案看起來更合理。如果這一切都成為可能的話,那么Java中使用閉包的地方將變得非常少了,語言根本沒必要提供這個(gè)特性。
話雖如此,但對于編程語言來說,持續(xù)不斷地平穩(wěn)發(fā)展還是非常重要的。因此本文探究了如下3種技術(shù)以向Java中增加新的語言特性而又不改變語言本身,他們 是客戶化領(lǐng)域特定語言(DSL)、Java 6的注解處理器(通過庫來增加可選的語言特性)以及將語法糖從語言遷移到IDE中。每項(xiàng)技術(shù)都可以讓眾多的主流開發(fā)者以非侵入的方式體驗(yàn)這些新特性,最棒 的想法則可以融入到語言核心當(dāng)中。
客戶化DSL
在這3項(xiàng)技術(shù)中,人們談?wù)撟疃嗟倪€是DSL。該術(shù)語的確切含義至今尚未統(tǒng)一,但出于討論的目的,我們在這里簡單地把它看作是用于解決特定問題、應(yīng)用范圍很窄 的一種語言而非用于解決所有計(jì)算問題的通用語言。這樣,DSL就并非是圖靈完備(non-Turing complete)的。當(dāng)然了,還是會有一些邊際情況存在的,比如說Postscript是一種圖靈完備的語言, 但根據(jù)我們方才的定義,它也是一種DSL。
如上所述,DSL并非新概念。其他類似的DSL還有正則表達(dá)式、XSLT、Ant以及JSP等等,所有這些都需要某種客戶化的解析器對其進(jìn)行處理。Martin Fowler還說fluent interfaces/API也可以看作是另一種DSL,稱之為內(nèi)部DSL。他說內(nèi)部DSL是直接在宿主語言中開發(fā)出來的。這對于Lisp和 Smalltalk開發(fā)者來說很容易理解,而最近Ruby社區(qū)也開始對內(nèi)部DSL情有獨(dú)鐘了。
雖然很多知名的DSL都是由商業(yè)公司開發(fā)和維護(hù)的,但一些企業(yè)開發(fā)團(tuán)隊(duì)也已經(jīng)使用該技術(shù)來創(chuàng)建能夠快速解決其問題的語言了,但畢竟還是小眾,這可能是 DSL領(lǐng)域門檻比較高的緣故吧。負(fù)責(zé)DSL的團(tuán)隊(duì)必須要設(shè)計(jì)語言、構(gòu)建解析器和其他工具來支持開發(fā)團(tuán)隊(duì),還要對每個(gè)新員工進(jìn)行培訓(xùn),讓其了解DSL的工作 機(jī)理。這時(shí),涌現(xiàn)出了能夠支援DSL開發(fā)的工具,這極大地改變了當(dāng)前的狀況。Intentional Software所開發(fā)的Intentional Domain Workbench比Java還要久遠(yuǎn),它首度實(shí)現(xiàn)了該工具的功能。
該項(xiàng)目創(chuàng)建于微軟研究院,Charles Simonyi博士在1995年所發(fā)表的論文“The Death of Computer Languages, the Birth of Intentional Programming”描繪了其愿景。2002年,Simonyi創(chuàng)建了Intentional Software以繼續(xù)實(shí)現(xiàn)其想法,大家可以看看介紹該系統(tǒng)的視頻,***震撼力。目前該產(chǎn)品的版本是1.0,但只有極少數(shù)的合作者能夠訪問。
其他一些軟件公司也在研究這個(gè)概念,其中就包括以IntelliJ IDEA Java IDE而揚(yáng)名天下的JetBrains,JetBrains最近發(fā)布了Meta Programming System(MPS)1.0版。MPS并沒有使用解析器而是直接使用了Abstract Syntax Tree(AST)。它提供了一個(gè)類似于文本的投影編輯器(projectional editor)以便程序員能夠操縱AST,同時(shí)該編輯器也可用于編寫語言和程序。當(dāng)程序員使用投影時(shí)就會為樹上的每個(gè)節(jié)點(diǎn)創(chuàng)建一個(gè)文本投影,這樣變換就會 反映到節(jié)點(diǎn)當(dāng)中。開發(fā)者可以通過這種方式以任意組合(通常稱之為語言組合)擴(kuò)展和嵌入語言。JetBrains正在內(nèi)部使用該產(chǎn)品,最近發(fā)布的bug追蹤 產(chǎn)品YouTrack就是使用該系統(tǒng)開發(fā)的。 #p#
Java 6注解處理器
相對于Ruby、Smalltalk和Lisp來說,DSL在很多主流語言(如Java)中的流行程度就稍遜一籌了,但最近Java語言的一些變化(尤其 是Java 6中新增的注解處理器)為開發(fā)者提供了新的機(jī)遇以在其中使用DSL。對于Java EE 6中的JPA 2.0來說,其某些API本身就是 DSL。注解處理器會為應(yīng)用中的每個(gè)持久化類建立一個(gè)元模型類型(metamodel type)。雖然開發(fā)者可以手工處理Java中的元模型,但這實(shí)在太無聊而且極易出錯(cuò)。注解處理器的出現(xiàn)改變了這一切,因?yàn)樗鼉?nèi)建于Java 6,因此無需特殊的IDE支持——IDE會代理編譯器所觸發(fā)的注解處理器,之后會自動(dòng)生成元數(shù)據(jù)模型。
程序庫也可以通過注解處理器來提供新的語言特性。比如說,Bruce Chapman的原型“no closures”提案就憑借該技術(shù)將方法轉(zhuǎn)換為 Single Abstract Method(SAM)類型,然后在Java 6上編譯。在與其交談過程中,Chapman指出SAM類型還支持自由變量(free variable),這是閉包的一個(gè)關(guān)鍵技術(shù),除了Single Abstract Method所需的參數(shù)外,方法體還可以通過@As.Additional注解聲明額外的參數(shù)。在獲得SAM類型的實(shí)例時(shí),這些參數(shù)可以帶有綁定值,然后在每次調(diào)用時(shí)傳遞給方法。
Chapman還創(chuàng)建了Rapt項(xiàng)目以探索該技術(shù)的其他使用場景,同時(shí)為語言的兩個(gè)變化提供了自己的實(shí)現(xiàn)——多行字符串(Multiline Strings)與XML字面值(XML literals)——這兩個(gè)特性是 為JDK 7準(zhǔn)備的,但卻不會包含到最終的發(fā)布中。Java甚至也可以使用這種方法實(shí)現(xiàn)閉包,Chapman對此說到,“我們剛剛使用該技術(shù)完成了一個(gè)Swing項(xiàng)目,在這個(gè)過程中發(fā)現(xiàn)了泛型的一些小bug,其中一個(gè)bug還沒有修復(fù),除此之外一切都很棒,沒人再想使用傳統(tǒng) 的匿名內(nèi)部類了?!?/p>
另一個(gè)探究注解處理器的項(xiàng)目是Lombok,它將該技術(shù)又向前推進(jìn)了一大步。Lombok將注解作為回調(diào)以運(yùn)行Java agent,后者會根據(jù)注解重寫各種javac內(nèi)核。由于操縱的是內(nèi)部類,因此它不太適合于產(chǎn)品使用(JVM各個(gè)小版本中的內(nèi)部類也可能不一樣),但該項(xiàng)目對于注解處理器到底能做什么這個(gè)問題上還是頗具啟發(fā)意義的,包括:通過@Getter和@Setter注解定義各種訪問級別的屬性,如@Setter(AccessLevel.PROTECTED) private String name:
@EqualsAndHashCode注解會根據(jù)對象中的屬性實(shí)現(xiàn)hashCode()和 equals()方法;
@ToString注解會實(shí)現(xiàn)toString()方法;
@data方法相當(dāng)于@ToString、@EqualsAndHashCode、所有屬性的@Getter以及所有非final屬性的@Setter的集合,可以使用 @data方法和構(gòu)造方法初始化final屬性。
還可以通過這種方式進(jìn)行其他的語言試驗(yàn),比如移除Java中的非運(yùn)行時(shí)異常等。雖然注解處理器技術(shù)為語言試驗(yàn)開辟了一條新航線,但還是要注意生成代碼的可讀性,保證開發(fā)者能讀懂生成的代碼。Chapman給出了很多建議:
要生成源代碼而不是字節(jié)碼,注意生成代碼的格式(尤其是縮進(jìn))。編譯器不在乎生成的代碼是不是都在同一行,但用戶在乎。我甚至還使用注解處理器在恰當(dāng)?shù)牡胤皆黾恿艘恍┳⑨尯蚸avadoc。如果這項(xiàng)技術(shù)逐漸流行起來,用戶將可以通過IDE查看編譯期所生成的代碼。
IDE中的語法糖
Bruce Chapman還提到了第三項(xiàng)技術(shù)——將語法糖從語言遷移到IDE中——他在博客中對該問題做過深入闡述。對于Java IDE來說,生成部分樣板代碼已成為不可或缺的功能了,比如類的getters和setters,但I(xiàn)DE開發(fā)者剛剛開始深挖該這個(gè)概念。 JetBrains的IntelliJ 9為內(nèi)部類提供了一個(gè)類似于閉包的簡潔的代碼塊語法,開 發(fā)者也可以自己加。
就像代碼折疊一樣,該語法會擴(kuò)展到編譯器能夠處理的完整的匿名內(nèi)部類——這樣堅(jiān)持使用標(biāo)準(zhǔn)的匿名內(nèi)部類語法的開發(fā)者很容易就適應(yīng)了。 Eclipse也有一個(gè)類似的插件。關(guān)鍵在于這種語法僅僅是實(shí)際代碼的另一種展示方式而已,編譯器和任何源代碼管理工具都能夠像以前那樣處 理他們。開發(fā)者可以在兩種方式間自由切換(就像代碼的展開與收起一樣),無權(quán)訪問該語法糖定義的人僅僅會看到正常的Java代碼。Chapman說到:
要想實(shí)現(xiàn)易于使用的目標(biāo)還有很多工作要做,但從長遠(yuǎn)來看,我發(fā)現(xiàn)開發(fā)者會很輕松地實(shí)現(xiàn)加糖/脫糖(sugaring/desugaring)的轉(zhuǎn)換(可以 參考jackpot來 了解實(shí)現(xiàn)原理)、不斷嘗試、不斷演進(jìn)并與同事和社區(qū)分享好的點(diǎn)子。這么做的好處與語言的演進(jìn)別無二致。***的東西會流行起來并形成實(shí)際語言演進(jìn)的基礎(chǔ),如 果必要的話還可以隨時(shí)去除該方法無法實(shí)現(xiàn)的“噪音”。
由于語法糖還要兼顧(非常多)其他的語言特性,因此無法提供完整的閉包支持;比如說BGGA閉包就有一些特性無法匹配匿名內(nèi)部類,因此不能通過這種方式實(shí)現(xiàn)。話雖如此,這種想 法卻展示了通過各種新語法來表示匿名內(nèi)部類的可行性,類似于BGGA語法或是FCM語法,開發(fā)者也可以選擇自己喜歡的語法。其他的語言特性(如null-safe Elvis operator)可以通過這種方式實(shí)現(xiàn)。要想進(jìn)一步驗(yàn)證該想法,可以體驗(yàn)一下這個(gè)NetBeans module(由Chapman開發(fā)),這正是他所說的用于 Properties的原型。
結(jié)論
在語言的發(fā)展過程中總是需要考慮穩(wěn)定與發(fā)展之間的平衡。上面介紹的技術(shù)所帶來的好處是他們不會影響平臺或是語言本身。這么做允許我們犯錯(cuò)誤,也有益于進(jìn)行快速激進(jìn)的試驗(yàn)。由于開發(fā)者能夠自由地進(jìn)行試驗(yàn),我們看到越來越多的人開始解決常見的樣板代碼“噪音”問題,如匿名內(nèi)部類語法等,同時(shí)將這些想法以合理的方式組織起來以獲得***的價(jià)值。我們將欣喜地看到開發(fā)者使用這些方法將Java平臺推向新的遠(yuǎn)方。
【編輯推薦】
- 深入理解Java的內(nèi)省與反射
- Java抽象類型二重唱 接口和抽象類
- 了解Java日志系統(tǒng)框架的設(shè)計(jì)與實(shí)現(xiàn)
- 淺析Java內(nèi)部類在GUI設(shè)計(jì)中的作用
- Java動(dòng)態(tài)模塊化運(yùn)行原理與實(shí)踐
網(wǎng)頁標(biāo)題:不改變語言如何助推Java的不斷演進(jìn)
文章路徑:http://fisionsoft.com.cn/article/dphhedg.html


咨詢
建站咨詢
