<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 實戰 Groovy: Groovy:Java 程序員的 DSL _用 Groovy 編寫更少的代碼,完成更多的工作_ Groovy 專家 Scott Davis 將重新開始撰寫 [_實戰 Groovy_](http://www.ibm.com/developerworks/cn/java/j-pg/) 系列文章,該系列文章于 2006 年停止編寫。作為開篇文章,本文將介紹 Groovy 最近的發展以及 Groovy 當前的狀態。然后了解_大約_ 從 2009 年開始,使用 Groovy 是多么輕松。 Andrew Glover 于 2004 年開始為 developerWorks 撰寫關于 Groovy 的文章,他先撰寫了 [_alt.lang.jre_](http://www.ibm.com/developerworks/cn/views/java/libraryview.jsp?search_by=alt.lang.jre) 系列中的介紹性文章 “[alt.lang.jre: 感受 Groovy](http://www.ibm.com/developerWorks/cn/java/j-alj08034/)”,又繼續撰寫了長期刊發的 [_實戰 Groovy_](http://www.ibm.com/developerworks/cn/java/j-pg/) 系列。發表這些文章時市場上還沒有出現關于 Groovy 的書籍(現在這樣的書籍超過十幾本),而且 Groovy 1.0 在幾年后才于 2007 年 1 月發布。自 2006 年末發布 _實戰 Groovy_ 的最后一期后,Groovy 發生了很大的變化。 現在,Groovy 每個月的平均下載數量大約為 35,000。Mutual of Omaha 等保守的公司擁有超過 70,000 行 Groovy 生產代碼。Groovy 在 Codehaus.org 中有一個最忙碌的郵件列表,這是托管該項目的位置(請參閱 [參考資料](#resources))。Grails 是惟一一個擁有較多下載數量以及繁忙郵件列表的項目,它是在 Groovy 中實現的流行 Web 框架(請參閱 [參考資料](#resources))。 在 JVM 中運行非 Java? 語言不僅常見,而且也是 Sun 的 JVM 策略的核心部分。Groovy 加入進了 Sun 支持的備選語言(如 JavaScript, JavaFX, JRuby 和 Jython)行列中。2004 年所做的實驗現在成為了最前沿的技術。 2009 年撰寫的關于 Groovy 的文章在許多方面與 Andy 開始撰寫的文章相同。2005 年確立的語法仍然保留至今。每個發行版都添加了引人注目的新功能,但是對于項目主管來說,保留向后兼容性是極為重要的。這項可靠的基礎使得 Java 開發組織在其應用程序進入生產環境并開始依賴各項技術時,毫不猶豫地選擇了 Groovy。 本文的目標是使經驗豐富的 Java 開發人員可以像 Groovy 開發人員一樣進行快速開發。不要被它的表面所蒙騙。本系列如名稱所示全部都是實際使用的 Groovy 實踐知識。在最開始編寫完 “Hello, World” 之后,請準備好盡管掌握實際的應用。 ## 關于本系列 Groovy 是運行在 Java 平臺上的現代編程語言。它將提供與現有 Java 代碼的無縫集成,同時引入閉包和元編程等出色的新功能。簡言之,Groovy 是 21 世紀根據 Java 語言的需要編寫的。 把任意一個新工具集成到開發工具包中的關鍵是:知道何時使用以及何時不應使用該工具。Groovy 可以提供強大的功能,但是必須正確地應用到適當的場景中。為此,[_實戰 Groovy_](http://www.ibm.com/developerworks/cn/java/j-pg/) 系列將探究 Groovy 的實際應用,幫助您了解何時及如何成功應用它們。 ## 安裝 Groovy 如果您以前從未使用過 Groovy,則首先需要安裝 Groovy。安裝步驟非常簡單,這些步驟與安裝 Ant 和 Tomcat 等常見 Java 應用程序甚至安裝 Java 平臺本身的步驟相同: 1. [下載](http://groovy.codehaus.org/Download) 最新的 Groovy ZIP 文件或 tarball。 2. 將存檔解壓縮到所選目錄中(您應當避免在目錄名稱中使用空格)。 3. 創建 `GROOVY_HOME` 環境變量。 4. 把 GROOVY_HOME/bin 添加到 `PATH` 中。 Groovy 運行在 Java 5 或 6 上的效果最佳。在命令提示中輸入 `java -version` 以確認您使用的是最新版本。然后鍵入 `groovy -version` 以確保 Groovy 已正確安裝。 所有主要 IDE(Eclipse、IntelliJ 和 NetBeans)都有支持自動完成和分步調試等功能的 Groovy 插件。雖然擁有一個優秀的 IDE 對于目前編寫 Java 代碼來說幾乎成為了一項必要要求,但是對于 Groovy 來說并非絕對。得益于 Groovy 語言的簡明性,許多人都選擇使用簡單的文本編輯器編寫。vi 和 Emacs 等常見開源編輯器都提供 Groovy 支持,Textpad(面向 Windows?)和 TextMate(面向 Mac OS X)等便宜的商業文本編輯器也提供 Groovy 支持(有關更多信息,請參閱 [參考資料](#resources))。 您稍后將在本文中看到,將 Groovy 與現有 Java 項目集成起來十分簡單。您只需將一個 Groovy JAR 從 GROOVY_HOME/embeddable 添加到類路徑中并把現有的 `javac` Ant 任務封裝到 `groovyc` 任務中(Maven 提供類似的支持)。 但是在掌握這些知識之前,我將從必修的 “Hello World” 示例開始。 * * * ## 進入 Groovy 世界 您知道 “Hello World” 示例應當會演示哪些內容 — 它是用給定語言可以編寫的最簡單的程序。清單 1 中所示的 “Hello World” Java 代碼的有趣之處在于,需要了解中間語言的知識才能完全了解代碼含義: ##### 清單 1\. 用 Java 代碼編寫的 “Hello World” 示例 ``` public class HelloJavaWorld{ public static void main(String[] args){ System.out.println("Hello Java World"); } } ``` 首先創建名為 HelloJavaWorld.java 的文件并輸入 `public class HelloJavaWorld`。許多剛開始使用 Java 的開發人員學到的第一課是如果類名與文件名不完全匹配(包括大小寫),則類無法編譯。另外,好奇的學生將在此時開始詢問關于 `public` 和 `private` 之類的訪問修飾符。 下一行 — `public static void main(String[] args)`— 通常將引發關于實現細節的一連串問題:什么是 `static`?什么是 `void`?為什么需要將方法命名為 `main`?什么是 `String` 數組?而最后,嘗試向剛開始使用 Java 的開發人員說明 `out` 是 `System` 類中的 `PrintStream` 對象的 `public`、`static`、`final` 實例。我永遠也忘不了學生說 “天哪!其實我只是想輸出 ‘Hello’”。 將此示例與用 Groovy 編寫的 “Hello World” 進行對照。創建名為 HelloGroovyWorld.groovy 的文件并輸入清單 2 中所示的代碼行: ##### 清單 2\. 用 Groovy 代碼編寫的 “Hello World” 示例 ``` println "Hello Groovy World" ``` 是的,這段代碼是與清單 1 中所示的 Java 示例等效的 Groovy 代碼。在本例中,所有實現細節 — 并不立即解決手頭問題的 “知識” — 都隱藏在后臺,只顯示簡單輸出 “Hello” 的代碼。輸入 `groovy HelloGroovyWorld` 以確認它可以工作。 這個小示例將演示 Groovy 的雙重價值:它將顯著地減少需要編寫的代碼行數,同時保留 Java 等效代碼的語義。在下一節中,您將進一步探究這種理念。 * * * ## 深入研究 Hello World 有經驗的 Java 開發人員都知道在 JVM 中運行代碼之前必須先編譯這些代碼。但是,Groovy 腳本在任何位置都不顯示為類文件。這是否意味著可以直接執行 Groovy 源代碼?答案是 “不一定,但是它看上去是這樣,對不對?” Groovy 解釋器將先在內存中編譯源代碼,然后再將其轉到 JVM 中。您可以通過輸入 `groovyc HelloGroovyWorld.groovy` 手動執行此步驟。但是,如果嘗試使用 `java` 運行得到的類,將顯示清單 3 中所示的異常: ##### 清單 3\. 嘗試在 `CLASSPATH` 中沒有 Groovy JAR 的情況下運行經過編譯的 Groovy 類 ``` $ java HelloGroovyWorld Exception in thread "main" java.lang.NoClassDefFoundError: groovy/lang/Script ``` 如前述,Groovy JAR 必須包含在 `CLASSPATH` 中。再次嘗試執行代碼,這一次把 `-classpath` 實參傳遞到 `java` 中,如清單 4 所示: ##### 清單 4\. 用 `java` 命令成功運行經過編譯的 Groovy 類 ``` //For UNIX, Linux, and Mac OS X $ java -classpath $GROOVY_HOME/embeddable/groovy-all-x.y.z.jar:. HelloGroovyWorld Hello Groovy World //For Windows $ java -classpath %GROOVY_HOME%/embeddable/groovy-all-x.y.z.jar;. HelloGroovyWorld Hello Groovy World ``` 現在您已經取得了一些進展。但是為了證明 Groovy 腳本真正地保留 Java 示例的語義,您需要深入鉆研字節碼。首先,輸入 `javap HelloJavaWorld`,如清單 5 所示: ##### 清單 5\. 解釋 Java 字節碼 ``` $ javap HelloJavaWorld Compiled from "HelloJavaWorld.java" public class HelloJavaWorld extends java.lang.Object{ public HelloJavaWorld(); public static void main(java.lang.String[]); } ``` 除了為您添加了 `javac` 編譯器之外,這段代碼中不應當有過多令人驚訝之處。您無需顯式輸入 `extends java.lang.Object` 或提供類的默認構造函數。 現在,輸入 `javap HelloGroovyWorld`,如清單 6 所示: ##### 清單 6\. 解釋 Groovy 字節碼 ``` $ javap HelloGroovyWorld Compiled from "HelloGroovyWorld.groovy" public class HelloGroovyWorld extends groovy.lang.Script{ ... public static void main(java.lang.String[]); ... } ``` ## 什么是 DSL? Martin Fowler 普及了特定于領域語言的理念(請參閱 [參考資料](#resources))。他把 DSL 定義為 “側重特定領域的表達有限的計算機編程語言”。“有限的表達” 并不是指語言的用途有限,只是表示這種語言提供了足夠用于適當表達 “特定領域” 的詞匯表。DSL 是一種很小的專用語言,這與 Java 語言等大型通用語言形成對比。 SQL 就是一種優秀的 DSL。您無法使用 SQL 編寫操作系統,但它是處理關系數據庫這一有限領域的理想選擇。在同樣意義上,Groovy 是 Java 平臺的 DSL,因為它是有限領域的 Java 開發的理想選擇。我在這里使用 _DSL_ 是為了啟發讀者,并不是特別的精確。如果我把 Groovy 稱為 _常用 Java 語言的內部 DSL_,可能更容易被 DSL 純粹主義者接受。 Dave Thomas 進一步闡明 DSL 的概念(請參閱 [參考資料](#resources))。他寫道,“無論領域專家在何時交流……他們都在說行業術語,這是他們為與同行進行有效交流而創造出的更簡略的專用語言”。可能將 Groovy 視為 “簡略的 Java 語言” 更能說明 Groovy 與 Java 語言之間的關系。本文的下一節將提供另一個示例。 在這里,您可以看到 `groovyc` 編譯器將獲取源文件的名稱并創建了一個同名的類(該類擴展 `groovy.lang.Script` 而非 `java.lang.Object`,這應當能幫助您理解嘗試在 `CLASSPATH` 中沒有 Groovy JAR 的情況下運行文件拋出 `NoClassDefFoundError` 異常的原因)。在所有其他編譯器提供的方法之中,您應當能夠找到一種優秀的舊 `public static void main(String[] args)` 方法。`groovyc` 編譯器把腳本行封裝到此方法中以保留 Java 語義。這意味著在使用 Groovy 時可以利用所有的現有 Java 知識。 例如,下面是在 Groovy 腳本中接受命令行輸入的方法。創建名為 Hello.groovy 的新文件并添加清單 7 中的代碼行: ##### 清單 7\. 接受命令行輸入的 Groovy 腳本 ``` println "Hello, " + args[0] ``` 現在在命令行中輸入 `groovy Hello Jane`。`args``String` 數組就在這里,就像任何一位 Java 開發人員期望的那樣。在這里使用 `args` 對于新手可能沒意義,但是它對于經驗豐富的 Java 開發人員意義非凡。 Groovy 將把 Java 代碼縮減為基本要素。您剛剛編寫的 Groovy 腳本幾乎和可執行的偽代碼一樣。表面上,該腳本簡單得足以讓新手能夠理解,但是對于經驗豐富的開發人員,它沒有去掉 Java 語言的底層強大功能。這就是我將 Groovy 視為 Java 平臺的特定于領域語言(DSL)的原因(請參閱 [什么是 DSL?](#dsl) 側欄)。 * * * ## 普通的舊 Groovy 對象 JavaBean — 或更通俗的名稱,普通的舊 Java 對象(Plain Old Java Object,POJO)— 是 Java 開發的主要支柱。在創建 POJO 以表示域對象時,您應當遵循定義好的一組期望。類應當為 `public`,并且字段應當為帶有一組對應的 `public` getter 和 setter 方法的 `private`。清單 8 顯示了一個典型的 Java POJO: ##### 清單 8\. Java POJO ``` public class JavaPerson{ private String firstName; private String lastName; public String getFirstName(){ return firstName; } public void setFirstName(String firstName){ this.firstName = firstName; } public String getLastName(){ return lastName; } public void setLastName(String lastName){ this.lastName = lastName; } } ``` 普通的舊 Groovy 對象(Plain Old Groovy Object,POGO)是 POJO 的簡化的替代者。它們完全保留了 POJO 的語義,同時顯著減少了需要編寫的代碼量。清單 9 顯示了用 Groovy 編寫的 “簡易” person 類: ##### 清單 9\. Groovy POGO ``` class GroovyPerson{ String firstName String lastName } ``` 除非您另外指定,否則 Groovy 中的所有類都是 `public` 的。所有屬性都是 `private` 的,而所有方法都是 `public` 的。編譯器將為每個屬性自動提供一組 `public` getter 和 setter 方法。用 `javac` 編譯 `JavaPerson` 并用 `groovyc` 編譯 `GroovyPerson`。現在通過 `javap` 運行它們以確認該 Groovy 示例擁有 Java 示例所擁有的所有內容,甚至可以擴展 `java.lang.Object`(在先前的 `HelloGroovyWorld` 示例中未指定類,因此 Groovy 轉而創建了擴展 `groovy.lang.Script` 的類)。 所有這些意味著您可以立即開始使用 POGO 作為 POJO 的替代選擇。Groovy 類是只剩下基本元素的 Java 類。在編譯了 Groovy 類之后,其他 Java 類可以輕松地使用它,就好像它是用 Java 代碼編寫的。為了證明這一點,請創建一個名為 JavaTest.java 的文件并添加清單 10 中的代碼: ##### 清單 10\. 從 Java 代碼中調用 Groovy 類 ``` public class JavaTest{ public static void main(String[] args){ JavaPerson jp = new JavaPerson(); jp.setFirstName("John"); jp.setLastName("Doe"); System.out.println("Hello " + jp.getFirstName()); GroovyPerson gp = new GroovyPerson(); gp.setFirstName("Jane"); gp.setLastName("Smith"); System.out.println("Hello " + gp.getFirstName()); } } ``` 即使 getter 和 setter 不顯示在 Groovy 源代碼中,這項測試也證明了它們是存在于經過編譯的 Groovy 類中并且完全可以正常運行。但是如果我不向您展示 Groovy 中的相應測試,則這個示例不算完整。創建一個名為 TestGroovy.groovy 的文件并添加清單 11 中的代碼: ##### 清單 11\. 從 Groovy 中調用 Java 類 ``` JavaPerson jp = new JavaPerson(firstName:"John", lastName:"Doe") println "Greetings, " + jp.getFirstName() + ". It is a pleasure to make your acquaintance." GroovyPerson gp = new GroovyPerson(lastName:"Smith", firstName:"Jane") println "Howdy, ${gp.firstName}. How the heck are you?" ``` 您首先可能會注意到,Groovy 提供的新構造函數允許您命名字段并按照所需順序指定這些字段。甚至更有趣的是,可以在 Java 類或 Groovy 類中使用此構造函數。這怎么可能?事實上,Groovy 先調用默認的無實參構造函數,然后調用每個字段的相應 setter。您可以模擬 Java 語言中的類似行為,但是由于 Java 語言缺少命名實參并且兩個字段都是 `Strings`,因此您無法按照任何順序傳入名字和姓氏字段。 接下來,注意 Groovy 支持傳統的 Java 方法來執行 `String` 串聯,以及在 `String` 中直接嵌入用 `${}` 圈起的代碼的 Groovy 方法(這些稱為 `GString`,它是 _Groovy Strings_ 的簡寫)。 最后,在類中調用 getter 時,您將看到使用 Groovy 語法的更多優點。您無需使用更冗長的 `gp.getFirstName()`,只需調用 `gp.firstName`。看上去您是在直接訪問字段,但是事實上您在調用后臺的相應的 getter 方法。Setter 將按照相同的方法工作:`gp.setLastName("Jones")` 和 `gp.lastName = "Jones"` 是等效的,后者將在后臺調用前者。 我希望您也能夠承認,在任何情況下,Groovy 都類似于簡易版的 Java 語言 — “領域專家” 可能使用 Groovy “與同行進行有效地交流”,或者類似于老朋友之間隨意的談笑。 * * * ## 歸根結底,Groovy 就是 Java 代碼 Groovy 最被低估的一個方面是它完全支持 Java 語法的事實。如前述,在使用 Groovy 時,您不必放棄一部分 Java 知識。在開始使用 Groovy 時,大部分代碼最終看上去都像是傳統的 Java 代碼。但是隨著您越來越熟悉新語法,代碼將逐漸發展為包含更簡明、更有表現力的 Groovy 風格。 要證明 Groovy 代碼可以看上去與 Java 代碼完全相同,請將 JavaTest.java 復制到 JavaTestInGroovy.groovy 中,然后輸入 `groovy JavaTestInGroovy`。您應當會看到同樣的輸出,但是請注意,您無需在運行前先編譯 Groovy 類。 此次演示應當使經驗豐富的 Java 開發人員能夠不假思索地選擇 Groovy。由于 Java 語法也是有效的 Groovy 語法,因此最開始的學習曲線實際上是不存在的。您可以將現有的 Java 版本與 Groovy、現有的 IDE 以及現有的生產環境結合使用。這意味著對您日常工作的干擾非常少。您只需確保 Groovy JAR 位于 `CLASSPATH` 中并調整構建腳本,以便 Groovy 類與 Java 類同時編譯。下一節將向您展示如何向 Ant build.xml 文件中添加 `groovyc` 任務。 * * * ## 用 Ant 編譯 Groovy 代碼 如果 `javac` 是可插拔的編譯器,則可以指示它同時編譯 Groovy 和 Java 文件。但是它不是,因此您只需用 `groovyc` 任務在 Ant 中封裝 `javac` 任務。這將允許 `groovyc` 編譯 Groovy 源代碼,并允許 `javac` 編譯 Java 源代碼。 當然,`groovyc` 既可以編譯 Java 文件,又可以編譯 Groovy 文件,但是還記得 `groovyc` 添加到 `HelloGroovyWorld` 和 `GroovyPerson` 中的額外的方便方法么?這些額外的方法也將被添加到 Java 類中。最好的方法可能就是讓 `groovyc` 編譯 Groovy 文件,而讓 `javac` 編譯 Java 文件。 要從 Ant 中調用 `groovyc`,請使用 `taskdef` 定義任務,然后像平時使用 `javac` 任務一樣使用 `groovyc` 任務(有關更多信息,請參閱 [參考資料](#resources))。清單 12 顯示了 Ant 構建腳本: ##### 清單 12\. 用 Ant 編譯 Groovy 和 Java 代碼 ``` <taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="my.classpath"/> <groovyc srcdir="${testSourceDirectory}" destdir="${testClassesDirectory}"> <classpath> <pathelement path="${mainClassesDirectory}"/> <pathelement path="${testClassesDirectory}"/> <path refid="testPath"/> </classpath> <javac debug="on" /> </groovyc> ``` 順便說一下,包含 `${}` 的 `String` 看上去疑似 `GString`,是不是?Groovy 是一種優秀的語言,它從各種其他語言和庫中借鑒了語法和功能。您經常會覺得似乎在其他語言中見過類似的特性。 * * * ## 結束語 這是一次 Groovy 旋風之旅。您了解了一些關于 Groovy 曾經的地位及其目前現狀的信息。您在系統中安裝了 Groovy,并且通過一些簡單的示例,了解了 Groovy 為 Java 開發人員提供的強大功能。 Groovy 不是運行在 JVM 上的惟一的備選語言。JRuby 是了解 Ruby 的 Java 開發人員的優秀解決方案。Jython 是了解 Python 的 Java 開發人員的優秀解決方案。但是正如您所見,Groovy 是了解 Java 語言的 Java 開發人員的優秀解決方案。Groovy 提供了類似 Java 的簡明語法,同時保留了 Java 語義,這一點非常引人注目。而且,采用新語言的路徑不包含 `del *.*` 或 `rm -Rf *` 是一次很好的變革,您不這樣認為嗎? 下期文章中,您將了解 Groovy 中的迭代。代碼通常需要逐項遍歷內容,不管它是列表、文件,還是 XML 文檔。您將看到非常普遍的 `each` 閉包。到那時,我希望您可以發現大量 Groovy 的實際應用。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看