在 IBM Bluemix 云平臺(tái)上開發(fā)并部署您的下一個(gè)應(yīng)用。 開始之前了解本教程的主要內(nèi)容,,以及如何從中獲得最大收獲,。 關(guān)于本教程如果現(xiàn)在有人要開始完全重寫 Java,那么 Groovy 就像是 Java 2.0,。Groovy 并沒有取代 Java,,而是作為 Java 的補(bǔ)充,它提供了更簡(jiǎn)單,、更靈活的語(yǔ)法,,可以在運(yùn)行時(shí)動(dòng)態(tài)地進(jìn)行類型檢查。您可以使用 Groovy 隨意編寫 Java 應(yīng)用程序,,連接 Java 模塊,,甚至擴(kuò)展現(xiàn)有的 Java 應(yīng)用程序 — 甚至可以用 Groovy 對(duì) Java 代碼進(jìn)行單元測(cè)試。Groovy 的美妙之處還在于,,它能夠比編寫純粹的 Java 代碼更快地完成所有工作 — 有時(shí)候會(huì)快許多,。 在本教程中,您將了解到 Groovy 是一門動(dòng)態(tài)語(yǔ)言,,它能夠像 Java 語(yǔ)言本身一樣很好地應(yīng)用于 Java 平臺(tái),。 學(xué)習(xí)目標(biāo)本教程將逐步向您介紹 Groovy 的基本概念。您將學(xué)習(xí) Groovy 集合,、Groovy 類,,當(dāng)然還有 Groovy 的語(yǔ)法。完成本教程之后,您將了解將 Java 和 Groovy 結(jié)合使用的好處,,從此您將能夠在日常的 Java 開發(fā)中使用 Groovy,。 前提條件為了從本教程得到最大收獲,您應(yīng)該熟悉 Java 語(yǔ)法和在 Java 平臺(tái)上進(jìn)行面向?qū)ο箝_發(fā)的基本概念,。 系統(tǒng)需求要嘗試本教程的代碼,,需要安裝以下環(huán)境之一: 另外,本章教程假設(shè)您正在使用 Eclipse IDE,。不需要安裝 Groovy,因?yàn)楸窘坛虝?huì)介紹如何安裝 Groovy Eclipse 插件,。 本教程推薦系統(tǒng)的配置如下:
本教程的操作說(shuō)明和示例均基于 Microsoft Windows 操作系統(tǒng),。本教程涉及的所有工具在 Linux 和 Unix 系統(tǒng)上也能工作,。 關(guān)于 Groovy這一節(jié)將學(xué)習(xí) Groovy 的基礎(chǔ)知識(shí):它是什么,它與 Java 語(yǔ)言和 JVM 的關(guān)系,,以及編寫 Groovy 代碼的一些要點(diǎn),。 什么是 Groovy?Groovy 是 JVM 的一個(gè)替代語(yǔ)言 —替代 是指可以用 Groovy 在 Java 平臺(tái)上進(jìn)行 Java 編程,,使用方式基本與使用 Java 代碼的方式相同,。在編寫新應(yīng)用程序時(shí),Groovy 代碼能夠與 Java 代碼很好地結(jié)合,,也能用于擴(kuò)展現(xiàn)有代碼,。目前的 Groovy 版本是 1.5.4,在 Java 1.4 和 Java 5 平臺(tái)上都能使用,,也能在 Java 6 上使用,。 Groovy 的一個(gè)好處是,它的語(yǔ)法與 Java 語(yǔ)言的語(yǔ)法很相似,。雖然 Groovy 的語(yǔ)法源于 Smalltalk 和 Ruby 這類語(yǔ)言的理念,,但是可以將它想像成 Java 語(yǔ)言的一種更加簡(jiǎn)單、表達(dá)能力更強(qiáng)的變體,。(在這點(diǎn)上,,Ruby 與 Groovy 不同,因?yàn)樗恼Z(yǔ)法與 Java 語(yǔ)法差異很大,。) 許多 Java 開發(fā)人員非常喜歡 Groovy 代碼和 Java 代碼的相似性,。從學(xué)習(xí)的角度看,如果知道如何編寫 Java 代碼,,那就已經(jīng)了解 Groovy 了,。Groovy 和 Java 語(yǔ)言的主要區(qū)別是:完成同樣的任務(wù)所需的 Groovy 代碼比 Java 代碼更少。(有時(shí)候會(huì)少很多!) Groovy 快捷方式開始使用 Groovy 時(shí),,您會(huì)發(fā)現(xiàn)它使日常的編程活動(dòng)變得快了許多,。完成本教程之后,您會(huì)了解更多的 Groovy 語(yǔ)法快捷方式,。不過(guò)現(xiàn)在只需知道以下這些要點(diǎn):
Groovy 的新增特性雖然 Groovy 允許省略 Java 語(yǔ)法中的一些元素,,但也增加了一些新特性,,例如本地集合、內(nèi)置的正則表達(dá)式和閉包,。在標(biāo)準(zhǔn)的 Java 代碼中,,如果想要?jiǎng)?chuàng)建一個(gè)項(xiàng)列表,首先要導(dǎo)入 關(guān)于閉包對(duì)于任何 Java 開發(fā)人員來(lái)說(shuō),,閉包都是一個(gè)令人興奮的新技巧。這些神奇的構(gòu)造將會(huì)包含在未來(lái)的 Java 發(fā)行版(很可能是 Java 7)中,,成為正式的 Java 語(yǔ)法,,但現(xiàn)在已經(jīng)可以在 Groovy 中使用了??梢詫?em>閉包 想像為一個(gè)代碼塊,,可以現(xiàn)在定義,以后再執(zhí)行,??梢允褂眠@些強(qiáng)大的構(gòu)造做許多漂亮的事,不過(guò)最著名的是簡(jiǎn)化迭代,。使用 Groovy 之后,,就有可能再也不需要編寫 動(dòng)態(tài)的 Groovy從技術(shù)上講,Groovy 可能是您最近聽說(shuō)過(guò)的類型最松散的動(dòng)態(tài)語(yǔ)言之一,。從這個(gè)角度講,,Groovy 與 Java 語(yǔ)言的區(qū)別很大,Java 語(yǔ)言是一種固定類型語(yǔ)言,。在 Groovy 中,,類型是可選的,所以您不必輸入 除此之外,,Groovy 代碼還能在運(yùn)行時(shí)輕松地改變自己。這實(shí)際上意味著,,能夠在運(yùn)行時(shí)輕松地為對(duì)象指定新方法和屬性,。這一編程領(lǐng)域稱為元編程,Groovy 能夠很好地支持這種編程方式,。在學(xué)習(xí)本教程的過(guò)程中,您將了解到關(guān)于 Groovy 的動(dòng)態(tài)性質(zhì)的更多內(nèi)容?,F(xiàn)在惟一要補(bǔ)充的是,,您會(huì)驚訝地發(fā)現(xiàn),在 Groovy 會(huì)使操作 XML 或普通的 一體兩面用 Groovy 編寫的任何內(nèi)容都可以編譯成標(biāo)準(zhǔn)的 Java 類文件并在 Java 代碼中重用,。類似地,用標(biāo)準(zhǔn) Java 代碼編寫的內(nèi)容也可以在 Groovy 中重用,。所以,,可以輕易地使用 Groovy 為 Java 代碼編寫單元測(cè)試。而且,,如果用 Groovy 編寫一個(gè)方便的小工具,,那么也可以在 Java 程序中使用這個(gè)小工具。 Groovy 初探學(xué)習(xí)新語(yǔ)言并不是件小事,,即使是 Groovy 也不例外,。這一節(jié)將介紹學(xué)習(xí) Groovy 的更多動(dòng)力。另外還將第一次看到一些 Groovy 代碼,,并了解 Groovy 與 Java 編程的比較,。 為什么要學(xué)習(xí) Groovy?即使 Groovy 與 Java 語(yǔ)言有許多相似之處,,它仍然是另一個(gè)語(yǔ)言,。您可能想知道為什么應(yīng)該花時(shí)間學(xué)習(xí)它。簡(jiǎn)單的回答就是:Groovy 是一種更有生產(chǎn)力 的語(yǔ)言,。它具有松散的語(yǔ)法和一些特殊功能,,能夠加快編碼速度。 只用一個(gè)示例即可說(shuō)明問(wèn)題:一旦發(fā)現(xiàn)使用 Groovy 在集合中導(dǎo)航的容易程度,您就再也不會(huì)用 Java 處理集合導(dǎo)航了,。能夠用 Groovy 快速編寫代碼,,這還意味著能夠更快地收到反饋,更不用說(shuō)完成任務(wù)列表中的工作帶來(lái)的滿足感了,。在較高層面上,,如果能更快地將代碼交付給利益相關(guān)者,那么就能在更短的時(shí)間內(nèi)交給他們更多發(fā)行版,。實(shí)際上,,Groovy 比 Java 更有助于敏捷開發(fā)。 入門非常容易如果仍然覺得采用新語(yǔ)言很困難,,那么可以看看將 Groovy 集成到開發(fā)環(huán)境有多么容易,。您無(wú)需安裝新的運(yùn)行時(shí)工具或?qū)iT的 IDE。實(shí)際上,,只需將 Groovy 的一個(gè) jar 文件放在類路徑中即可,。 而且,Groovy 是一種開源語(yǔ)言,,由熱心的 Java 開發(fā)人員社區(qū)管理,。因?yàn)?Groovy 獲得 Apache Software License, Version 2.0,所以可以自由地使用它開發(fā)自由軟件和私有軟件,。 Groovy 和 Java 語(yǔ)言對(duì)比買車的時(shí)候,,如果不試駕一下,是不會(huì)買的,。所以,,在要求您安裝 Groovy 之前,我會(huì)演示一些代碼,。首先,,回顧一下用 Java 如何創(chuàng)建、編譯和運(yùn)行標(biāo)準(zhǔn)的 Hello World 示例,;然后再看看如何使用 Groovy 代碼執(zhí)行同一過(guò)程,。比較這兩個(gè)示例,很容易就能看到這兩種語(yǔ)言之間的差異,。 用 Java 編寫的 Hello World用 Java 編寫的典型的 Hello World 示例如下所示: public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } 編譯和運(yùn)行 Java 示例在這個(gè)簡(jiǎn)單的 c:>javac HelloWorld.java 最后,運(yùn)行經(jīng)過(guò)編譯的類: c:>java HelloWorld 迄今為止還不錯(cuò) — 很久以前就會(huì)編這么基礎(chǔ)的代碼了,,所以這里只是回顧一下,。下面,,請(qǐng)看用 Groovy 編碼的相同過(guò)程。 用 Groovy 編寫的 Hello World就像前面提到過(guò)的,,Groovy 支持松散的 Java 語(yǔ)法 — 例如,,不需要為打印 “Hello World!” 這樣的簡(jiǎn)單操作定義類。 而且,,Groovy 使日常的編碼活動(dòng)變得更容易,,例如,Groovy 允許輸入 所以,,用 Groovy 編寫 Hello World 程序就如下面這樣簡(jiǎn)單: println "Hello World!" 請(qǐng)注意,在這段代碼周圍沒有類結(jié)構(gòu),,而且也沒有方法結(jié)構(gòu),!我還使用 運(yùn)行 Groovy 示例假設(shè)我將代碼保存在文件 MyFirstExample.groovy 內(nèi),,只要輸入以下代碼就能運(yùn)行這個(gè)示例: c:>groovy MyFirstExample.groovy 在控制臺(tái)上輸出 “Hello World!” 所需的工作就這么多,。 快捷方式應(yīng)用您可能注意到了,我不必編譯 Groovy 允許完全省略編譯步驟,不過(guò)仍然可以 進(jìn)行編譯,。如果想要編譯代碼,,可以使用 Groovy 編譯器 至于運(yùn)行代碼,,如果我希望更加簡(jiǎn)潔,,我甚至還能輸入 c:>groovy -e "println 'Hello World!'" 這會(huì)生成相同的結(jié)果,而且甚至無(wú)需定義任何文件,! Groovy 入門在這一節(jié)中,,將真正開始進(jìn)行 Groovy 編程,。首先,學(xué)習(xí)如何輕松地安裝 Groovy(通過(guò) Eclipse Groovy 插件),,然后從一些有助于了解 Groovy 的簡(jiǎn)單示例開始,。 輕松安裝 Groovy為了迅速開始使用 Groovy,需要做的全部工作就是安裝 Eclipse 的 Groovy 插件,。打開 Ecliplse,,在 Help 菜單中選擇 Software Updates > Find and Install...。 圖 1 顯示了執(zhí)行以上步驟之后出現(xiàn)的對(duì)話框: 圖 1. Eclipse Feature Updates 對(duì)話框在選項(xiàng)中導(dǎo)航接下來(lái),,出現(xiàn)一個(gè)對(duì)話框,,里面包含兩個(gè)選項(xiàng)。請(qǐng)選擇 Search for new features to install 單選按鈕,。單擊 Next 按鈕,,然后選擇 New Remote Site...。出現(xiàn)一個(gè)新的對(duì)話框,,里面包含兩個(gè)需要填寫的字段:新位置的名稱和該位置的 URL,,如圖 2 所示: 圖 2. 確保為新的遠(yuǎn)程站點(diǎn)提供了正確的 URL輸入 “ 圖 3.Eclipse 中的遠(yuǎn)程網(wǎng)站清單完成安裝單擊 Finish 按鈕之后,,應(yīng)該會(huì)出現(xiàn) Search Results 對(duì)話框,。請(qǐng)?jiān)俅未_定選中了 “Groovy plugin” 框并單擊 Next 按鈕,這一步驟如圖 4 所示: 圖 4. 選擇 Groovy 插件經(jīng)過(guò)一系列確認(rèn)之后,,將會(huì)下載插件,,然后可能需要重新啟動(dòng) Eclipse。 創(chuàng)建 Groovy 項(xiàng)目Eclipse 重啟之后,,就能夠創(chuàng)建第一個(gè) Groovy 項(xiàng)目了,。請(qǐng)確保創(chuàng)建兩個(gè)源文件夾 — 一個(gè)稱為 “groovy”,另一個(gè)稱為 “java”,。編寫的 Groovy 代碼放在 groovy 文件夾,,Java 代碼放在 java 文件夾。我發(fā)現(xiàn)將二者分開將會(huì)很有用,,如圖 5 所示: 圖 5. 兩個(gè)源文件夾 — Java 和 Groovy將 Groovy 導(dǎo)入項(xiàng)目項(xiàng)目創(chuàng)建之后,,右鍵單擊項(xiàng)目的圖標(biāo),應(yīng)該會(huì)看到一個(gè) Groovy 選項(xiàng),,如圖 6 所示,。請(qǐng)選擇該選項(xiàng),然后選擇 Add Groovy Nature 選項(xiàng),。這樣做可以將必要的 Groovy 庫(kù),、編譯器和運(yùn)行程序?qū)氲巾?xiàng)目中,。 圖 6. 在 Eclipse 中添加 Groovy 特性創(chuàng)建 Groovy 類創(chuàng)建 Groovy 類很簡(jiǎn)單。選擇 圖 7. 通過(guò) New 菜單創(chuàng)建 Groovy 類給類命名在這里,,找到 Groovy 文件夾,,并選擇 Groovy Class— 應(yīng)該會(huì)看到一個(gè)對(duì)話框,如圖 8 所示,。 圖 8.選擇創(chuàng)建 Groovy 類單擊 Next 按鈕,,系統(tǒng)將要求您提供類的名稱。輸入 現(xiàn)在可以將 圖 9. 現(xiàn)在不必考慮包的問(wèn)題,!雖然步驟看起來(lái)很多,但這與創(chuàng)建標(biāo)準(zhǔn)的 Java 類并沒有什么區(qū)別,。 Hello World! — 用 Groovy 編寫的 Java 程序單擊 Finish 按鈕,,應(yīng)該會(huì)看到如下所示的代碼段: class HelloWorld { static void main(args) { } } 這看起來(lái)同前面的 Java 編譯程序現(xiàn)在在 class HelloWorld { static void main(args) { println "Hello World" } } 在源代碼編輯器中應(yīng)該能夠右鍵單擊,,并選擇 Compile Groovy File 選項(xiàng),,如圖 10 所示,。 圖 10. 右鍵單擊 Groovy 文件即可進(jìn)行編譯運(yùn)行程序接下來(lái),,再次右鍵單擊文件,選擇 Run As 選項(xiàng),,然后選擇 Groovy 選項(xiàng),。在 Eclipse 控制臺(tái)中應(yīng)該會(huì)看到輸出的 “Hello World”,如圖 11 所示,。 圖 11. 輸出的 Hello World學(xué)到了什么,?OK,那么這是一種突出重點(diǎn)的取巧方式,。Groovy 實(shí)際上就是 Java,。其語(yǔ)法不同 — 多數(shù)情況下會(huì)短一些 — 但 Groovy 代碼 100% 符合 Java 字節(jié)碼標(biāo)準(zhǔn),。下一節(jié)將進(jìn)一步介紹這兩種語(yǔ)言的交叉。 Groovy 變身為 Java前面已經(jīng)看到 Groovy 與 Java 代碼實(shí)際上可以互換的第一個(gè)證據(jù),。這一節(jié)將進(jìn)一步證明這點(diǎn),,繼續(xù)使用 Groovy 構(gòu)建的 Hello, Java!為了使您確信 Groovy 就是 Java,,現(xiàn)在在 public class HelloWorld { public static void main(args) { println "Hello World" } } 還不確信?這個(gè)代碼運(yùn)行起來(lái)同前面的代碼完全一樣,。但是,,如果仍不確信,還可以在 public class HelloWorld { public static void main(String[]args) { println "Hello World" } } 現(xiàn)在還沒完現(xiàn)在,,還可以將 public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World") } } 現(xiàn)在的代碼與前面用 Java 編寫的 Hello World 示例完全相同,但是哪個(gè)示例更容易編寫呢,? 請(qǐng)注意,,原來(lái)的基于 Groovy 的 Hello, Groovy!如果喜歡,可以將這個(gè)過(guò)程完全翻轉(zhuǎn)過(guò)來(lái),,回到基于 Java 的 Hello World 示例,,刪除文件里的所有內(nèi)容,只保留 println "Hello World" 現(xiàn)在,哪個(gè)程序更容易編寫呢,? 運(yùn)行程序,!Groovy 代碼完全符合 Java 字節(jié)碼標(biāo)準(zhǔn),這個(gè)練習(xí)證明了這一點(diǎn),。在 Eclipse 中,,選擇 Run 菜單選項(xiàng) Open Run Dialog...。選擇一個(gè)新的 Java Application 配置,。確保項(xiàng)目是您的 Groovy 項(xiàng)目,。對(duì)于 在圖 12 中可以看到整個(gè)這個(gè)過(guò)程 — 如果以前在 Eclipse 中運(yùn)行過(guò) Java 類,,那么您應(yīng)該對(duì)這個(gè)過(guò)程很熟悉,。 圖 12. Groovy 代碼完全符合 Java 字節(jié)碼標(biāo)準(zhǔn)單擊 Run 按鈕,看到什么了,?實(shí)際上,,“Hello World!” 從未像現(xiàn)在這樣能夠說(shuō)明問(wèn)題。 Groovy 是沒有類型的 Java 代碼很可能將 Groovy 當(dāng)成是沒有規(guī)則的 Java 代碼,。但實(shí)際上,,Groovy 只是規(guī)則少一些。這一節(jié)的重點(diǎn)是使用 Groovy 編寫 Java 應(yīng)用程序時(shí)可以不用考慮的一個(gè) Java 編程的具體方面:類型定義,。 為什么要有類型定義,?在 Java 中,如果要聲明一個(gè) String value = "Hello World"; 但是,,如果仔細(xì)想想,就會(huì)看出,,等號(hào)右側(cè)的字符已經(jīng)表明 def value = "Hello World" 實(shí)際上,Groovy 會(huì)根據(jù)對(duì)象的值來(lái)判斷它的類型,。 運(yùn)行程序,!將 HelloWorld.groovy 文件中的代碼編輯成下面這樣: String message = "Hello World" println message 運(yùn)行這段代碼,應(yīng)該會(huì)在控制臺(tái)上看到與前面一樣的 “Hello World”?,F(xiàn)在,,將變量類型 除了輸出 def message = "Hello World" println message.class 輸出 “ 類型推斷的更多內(nèi)容您可能聽說(shuō)過(guò),,在 Groovy 中 “一切都是對(duì)象” — 但對(duì)于類型來(lái)說(shuō)這句話意味著什么呢,?讓我們看看如果將前面示例中的 def message = 12 println message.class
Java 中的所有對(duì)象都擴(kuò)展自 繼續(xù)使用這段代碼。將 無(wú)類型有什么意義那么,,Groovy 缺少類型意味著所需的輸入更少。不可否認(rèn),,將 所以,,只需要使用 通過(guò) Groovy 進(jìn)行循環(huán)同大多數(shù)腳本語(yǔ)言一樣,Groovy 經(jīng)常被宣傳為生產(chǎn)力更高 的 Java 語(yǔ)言替代品,。您已經(jīng)看到了 Groovy 缺少類型能夠如何減少打字工作,。在這一節(jié),將創(chuàng)建并試用一個(gè) 更好,、更短的循環(huán)下面這種方法可以更好地感受 Groovy 缺乏類型的好處:首先,,用與創(chuàng)建 def repeat(val){ for(i = 0; i < 5; i++){ println val } } 起初,,從 Java 的角度來(lái)看,這個(gè)小函數(shù)看起來(lái)可能有些怪(實(shí)際上,,它很像 JavaScript),。但它就是 Java 代碼,只不過(guò)是用 Groovy 的樣式編寫的,。 深入方法
調(diào)用這個(gè)函數(shù),。 repeat("hello world") 會(huì)輸出 “hello world” 五次。請(qǐng)注意,, Groovy 中的范圍范圍 是一系列的值,。例如 “ 循環(huán)范圍范圍為循環(huán)帶來(lái)了很大的方便,。例如,前面從 0 遞增到 4 的 for(i = 0; i < 5; i++) 范圍可以將這個(gè) def repeat(val){ for(i in 0..5){ println val } } 設(shè)置范圍如果運(yùn)行這個(gè)示例,,可能會(huì)注意到一個(gè)小問(wèn)題:“Hello World” 輸出了六次而不是五次,。這個(gè)問(wèn)題有三種解決方法:
不論采用哪種方法,都會(huì)得到原來(lái)的效果 — 輸出 “Hello World” 五次,。 默認(rèn)參數(shù)值現(xiàn)在已經(jīng)成功地使用 Groovy 的范圍表達(dá)式縮短了 每次調(diào)用 Groovy 支持默認(rèn)參數(shù)值,,可以在函數(shù)或方法的正式定義中指定參數(shù)的默認(rèn)值。調(diào)用函數(shù)的程序可以選擇省略參數(shù),,使用默認(rèn)值,。 更加復(fù)雜的參數(shù)值使用前面的 def repeat(val, repeat=5){ for(i in 0..<repeat){ println val } } 像下面這樣調(diào)用該函數(shù): repeat("Hello World", 2) repeat("Goodbye sunshine", 4) repeat("foo") 結(jié)果會(huì)輸出 “Hello World” 兩次,,“Goodbye sunshine” 四次,“foo” 五次(默認(rèn)次數(shù)),。 Groovy 集合在 Groovy 提供的所有方便的快捷方式和功能中,,最有幫助的一個(gè)可能就是內(nèi)置的 集合?;叵胍幌略?Java 編程中是如何使用集合的 — 導(dǎo)入 而 Groovy 可以直接在語(yǔ)言內(nèi)使用集合。在 Groovy 中,,不需要導(dǎo)入專門的類,,也不需要初始化對(duì)象。集合是語(yǔ)言本身的本地成員,。Groovy 也使集合(或者列表)的操作變得非常容易,,為增加和刪除項(xiàng)提供了直觀的幫助。 可以將范圍當(dāng)作集合在前一節(jié)學(xué)習(xí)了如何用 Groovy 的范圍將循環(huán)變得更容易,。范圍表達(dá)式 “ def range = 0..4 println range.class assert range instanceof List 請(qǐng)注意, 豐富的支持Groovy 的集合支持相當(dāng)豐富,,而且美妙之處就在于,,在 Groovy 的魔法背后,一切都是標(biāo)準(zhǔn)的 Java 對(duì)象,。每個(gè) Groovy 集合都是 前面提到過(guò),Groovy 的語(yǔ)法提供了本地列表和映射,。例如,,請(qǐng)將以下兩行代碼添加到 def coll = ["Groovy", "Java", "Ruby"] assert coll instanceof Collection assert coll instanceof ArrayList 你將會(huì)注意到, Collection<String> coll = new ArrayList<String>(); coll.add("Groovy"); coll.add("Java"); coll.add("Ruby"); 在 Java 代碼中,,必須使用 添加項(xiàng)Groovy 提供了許多方法可以將項(xiàng)添加到列表 — 可以使用 例如,下面的每一行代碼都會(huì)向底層集合加入一些項(xiàng): coll.add("Python") coll << "Smalltalk" coll[5] = "Perl"
請(qǐng)注意,,Groovy 支持操作符重載 — 檢索非常輕松如果需要從集合中得到某個(gè)特定項(xiàng),可以通過(guò)像上面那樣的位置參數(shù)獲取項(xiàng),。例如,,如果想得到第二個(gè)項(xiàng) “Java”,可以編寫下面這樣的代碼(請(qǐng)記住集合和數(shù)組都是從 0 開始): assert coll[1] == "Java" Groovy 還允許在集合中增加或去掉集合,,如下所示: def numbers = [1,2,3,4] assert numbers + 5 == [1,2,3,4,5] assert numbers - [2,3] == [1,4] 請(qǐng)注意,,在上面的代碼中,, 實(shí)際上創(chuàng)建了新的 集合實(shí)例,由最后一行可以看出,。 魔法方法Groovy 還為集合添加了其他一些方便的功能,。例如,可以在集合實(shí)例上調(diào)用特殊的方法,,如下所示: def numbers = [1,2,3,4] assert numbers.join(",") == "1,2,3,4" assert [1,2,3,4,3].count(3) == 2
假設(shè)有一個(gè) assert ["JAVA", "GROOVY"] == ["Java", "Groovy"]*.toUpperCase() 請(qǐng)注意 Groovy 映射除了豐富的列表處理功能,,Groovy 還提供了堅(jiān)固的映射機(jī)制,。同列表一樣,映射也是本地?cái)?shù)據(jù)結(jié)構(gòu),。而且 Groovy 中的任何映射機(jī)制在幕后都是 Java 語(yǔ)言中的映射Java 語(yǔ)言中的映射是名稱-值對(duì)的集合。所以,,要用 Java 代碼創(chuàng)建典型的映射,,必須像下面這樣操作: Map<String, String>map = new HashMap<String, String>(); map.put("name", "Andy"); map.put("VPN-#","45"); 一個(gè) 通過(guò) Groovy 進(jìn)行映射Groovy 使得處理映射的操作像處理列表一樣簡(jiǎn)單 — 例如,,可以用 Groovy 將上面的 Java 映射寫成 def hash = [name:"Andy", "VPN-#":45] 請(qǐng)注意,Groovy 映射中的鍵不必是 全都是 Java接下來(lái)創(chuàng)建一個(gè)新類 assert hash.getClass() == java.util.LinkedHashMap 可以看到 Groovy 使用了 Java 的 hash.put("id", 23) assert hash.get("name") == "Andy" 有 groovy 特色的映射現(xiàn)在您已經(jīng)看到,,Groovy 給任何語(yǔ)句都施加了魔法,,所以可以用 hash.dob = "01/29/76"
assert hash.dob == "01/29/76" 當(dāng)然 位置映射還可以使用假的位置語(yǔ)法將項(xiàng)放入映射,,或者從映射獲取項(xiàng)目,,如下所示: assert hash["name"] == "Andy" hash["gender"] = "male" assert hash.gender == "male" assert hash["gender"] == "male"
但是,請(qǐng)注意,,在使用 Groovy 中的閉包現(xiàn)在,,閉包是 Java 世界的一個(gè)重大主題,,對(duì)于是否會(huì)在 Java 7 中包含閉包仍然存在熱烈的爭(zhēng)論。有些人會(huì)問(wèn):既然 Groovy 中已經(jīng)存在閉包,,為什么 Java 語(yǔ)言中還需要閉包,?這一節(jié)將學(xué)習(xí) Groovy 中的閉包。如果沒有意外,,在閉包成為 Java 語(yǔ)法的正式部分之后,,這里學(xué)到的內(nèi)容將給您帶來(lái)方便。 不再需要更多迭代雖然在前幾節(jié)編寫了不少集合代碼,,但還沒有實(shí)際地在集合上迭代,。當(dāng)然,您知道 Groovy 就是 Java,,所以如果愿意,,那么總是能夠得到 Java 的 def acoll = ["Groovy", "Java", "Ruby"] for(Iterator iter = acoll.iterator(); iter.hasNext();){ println iter.next() } 實(shí)際上在 能否看見閉包,?對(duì)于上面的代碼,可以用更簡(jiǎn)潔的方式對(duì)集合進(jìn)行迭代,,如下所示: def acoll = ["Groovy", "Java", "Ruby"] acoll.each{ println it } 請(qǐng)注意,, 執(zhí)行代碼閉包是可執(zhí)行的代碼塊。它們不需要名稱,,可以在定義之后執(zhí)行,。所以,在上面的示例中,,包含輸出 在較高層面上, 圖 13. 迭代從未像現(xiàn)在這樣容易閉包中的 def acoll = ["Groovy", "Java", "Ruby"] acoll.each{ value -> println value } 在這個(gè)示例中,,用 迭代無(wú)處不在閉包在 Groovy 中頻繁出現(xiàn),,但是,,通常用于在一系列值上迭代的時(shí)候。請(qǐng)記住,,一系列值可以用多種方式表示,,不僅可以用列表表示 — 例如,可以在映射,、 如果想在前面一節(jié) “Groovy 中的映射” 中的 def hash = [name:"Andy", "VPN-#":45] hash.each{ key, value -> println "${key} : ${value}" } 請(qǐng)注意,,閉包還允許使用多個(gè)參數(shù) — 在這個(gè)示例中,,上面的代碼包含兩個(gè)參數(shù)( 使用 Java 代碼迭代以下是使用典型的 Java 構(gòu)造如何進(jìn)行同樣的迭代: Map<String, String>map = new HashMap<String, String>(); map.put("name", "Andy"); map.put("VPN-#","45"); for(Iterator iter = map.entrySet().iterator(); iter.hasNext();){ Map.Entry entry = (Map.Entry)iter.next(); System.out.println(entry.getKey() + " : " + entry.getValue()); } 上面的代碼比 Groovy 的代碼長(zhǎng)得多,,是不是,?如果要處理大量集合,,那么顯然用 Groovy 處理會(huì)更方便。 迭代總結(jié)請(qǐng)記住,,凡是集合或一系列的內(nèi)容,,都可以使用下面這樣的代碼進(jìn)行迭代。 "ITERATION".each{ println it.toLowerCase() } 閉包的更多使用方式雖然在迭代上使用閉包的機(jī)會(huì)最多,,但閉包確實(shí)還有其他用途,。因?yàn)殚]包是一個(gè)代碼塊,所以能夠作為參數(shù)進(jìn)行傳遞(Groovy 中的函數(shù)或方法不能這樣做),。閉包在調(diào)用的時(shí)候才會(huì)執(zhí)行這一事實(shí)(不是在定義的時(shí)候)使得它們?cè)谀承﹫?chǎng)合上特別有用,。 例如,通過(guò) Eclipse 創(chuàng)建一個(gè) def excite = { word -> return "${word}!!" } 這段代碼是名為 延遲執(zhí)行既然有了閉包,,下面就該實(shí)際使用它了??梢酝ㄟ^(guò)兩種方法調(diào)用閉包:直接調(diào)用或者通過(guò)
繼續(xù)使用 assert "Groovy!!" == excite("Groovy") assert "Java!!" == excite.call("Java") 可以看到,,兩種調(diào)用方式都能工作,,但是直接調(diào)用的方法更簡(jiǎn)潔。不要忘記閉包在 Groovy 中也是一類對(duì)象 — 既可以作為參數(shù)傳遞,,也可以放在以后執(zhí)行,。用普通的 Java 代碼可以復(fù)制同樣的行為,但是不太容易?,F(xiàn)在不會(huì)感到驚訝了吧,? Groovy 中的類迄今為止,您已經(jīng)用 Groovy 輸出了許多次 “Hello World”,,已經(jīng)操作了集合,,用閉包在集合上迭代,也定義了您自己的閉包。做所有這些工作時(shí),,甚至還沒有討論那個(gè)對(duì) Java 開發(fā)人員來(lái)說(shuō)至關(guān)重要的概念 — 類,。 當(dāng)然,您已經(jīng)在這個(gè)教程中使用過(guò)類了:您編寫的最后幾個(gè)示例就是在不同類的 Song 類我們先從用 Groovy 定義一個(gè)簡(jiǎn)單的 JavaBean 形式的類開始,這個(gè)類稱為
第一步自然是用 Groovy 創(chuàng)建名為 創(chuàng)建這個(gè)類之后,,刪除 Groovy 插件自動(dòng)生成的 歌曲有一些屬性 — 創(chuàng)作歌曲的藝術(shù)家,、歌曲名稱,、風(fēng)格等等。請(qǐng)將這些屬性加入新建的 package org.acme.groovy class Song { def name def artist def genre } 迄今為止還不錯(cuò),,是不是,?對(duì)于 Grooovy 的新開發(fā)人員來(lái)說(shuō),,還不算太復(fù)雜! Groovy 類就是 Java 類應(yīng)該還記得本教程前面說(shuō)過(guò) Groovy 編譯器為用 Groovy 定義的每個(gè)類都生成標(biāo)準(zhǔn)的 Java 這意味著,,如果想在另一個(gè) Groovy 類或 Java 類中使用新建的 接下來(lái)創(chuàng)建一個(gè)新類,,名為 現(xiàn)在應(yīng)該看到如下所示的代碼: package org.thirdparty.lib class SongExample { static void main(args) {} } 類的關(guān)系現(xiàn)在是使用 package org.thirdparty.lib import org.acme.groovy.Song class SongExample { static void main(args) { def sng = new Song(name:"Le Freak", artist:"Chic", genre:"Disco") } } 現(xiàn)在 類初始化Groovy 自動(dòng)提供一個(gè)構(gòu)造函數(shù),構(gòu)造函數(shù)接受一個(gè)名稱-值對(duì)的映射,,這些名稱-值對(duì)與類的屬性相對(duì)應(yīng),。這是 Groovy 的一項(xiàng)開箱即用的功能 — 用于類中定義的任何屬性,Groovy 允許將存儲(chǔ)了大量值的映射傳給構(gòu)造函數(shù),。映射的這種用法很有意義,,例如,您不用初始化對(duì)象的每個(gè)屬性,。 也可以添加下面這樣的代碼: def sng2 = new Song(name:"Kung Fu Fighting", genre:"Disco") 也可以像下面這樣直接操縱類的屬性: def sng3 = new Song() sng3.name = "Funkytown" sng3.artist = "Lipps Inc." sng3.setGenre("Disco") assert sng3.getArtist() == "Lipps Inc." 從這個(gè)代碼中明顯可以看出,,Groovy 不僅創(chuàng)建了一個(gè)構(gòu)造函數(shù),允許傳入屬性及其值的映射,,還可以通過(guò) 在進(jìn)行屬性操縱時(shí),,非常有 Groovy 特色的是:總是會(huì)調(diào)用 setter 和 getter 方法 — 即使直接通過(guò) 核心的靈活性Groovy 是一種本質(zhì)上就很靈活的語(yǔ)言,。例如,,看看從前面的代碼中將 sng3.setGenre "Disco" assert sng3.genre == "Disco" 在 Groovy 中,,對(duì)于接受參數(shù)的方法,,可以省略括號(hào) — 在某些方面,這樣做會(huì)讓代碼更容易閱讀,。 方法覆蓋迄今為止已經(jīng)成功地創(chuàng)建了 println sng3 在 Java 中這樣只會(huì)輸出所有對(duì)象的默認(rèn) 在 String toString(){ "${name}, ${artist}, ${genre}" } 根據(jù)本教程已經(jīng)學(xué)到的內(nèi)容,,可以省略 不需要 return您可能已經(jīng)想到:在 Groovy 中可以省略 重新運(yùn)行 特殊訪問(wèn)Groovy 的自動(dòng)生成功能對(duì)于一些功能來(lái)說(shuō)很方便,,但有些時(shí)候需要覆蓋默認(rèn)的行為。例如,,假設(shè)需要覆蓋 提供這個(gè)新行為很容易,,只要定義 def getGenre(){ genre.toUpperCase() } 同以前一樣,這個(gè)簡(jiǎn)單方法省略了返回類型和 空指針安全性如果您一直在跟隨本教程,,那么應(yīng)該已經(jīng)在 assert sng3.genre == "Disco" 結(jié)果在重新運(yùn)行 幸運(yùn)的是,可以輕松地修復(fù)這個(gè)錯(cuò)誤:只要在 println sng2.artist.toUpperCase() 但是現(xiàn)在控制臺(tái)上出現(xiàn)了更多的 紅色文本 — 出什么事了,?! 可惡的 null如果回憶一下,,就會(huì)想起 幸運(yùn)的是,, Groovy 通過(guò) 例如,,將 重新運(yùn)行 def sng4 = new Song(name:"Thriller", artist:"Michael Jackson") println sng4 就是 Java您將會(huì)注意到,,雖然預(yù)期可能有異常,,但是沒有生成異常。即使沒有定義 您還記得 Groovy 就是 Java,對(duì)吧,?所以在 String toString(){ "${name}, ${artist}, ${getGenre()}" } 重新運(yùn)行 另一個(gè)方便的小操作符希望您做的修改與我的類似,。在下面將會(huì)看到,,我進(jìn)一步擴(kuò)充了 def getGenre(){ genre?.toUpperCase() }
對(duì) Groovy 進(jìn)行單元測(cè)試本教程一直都強(qiáng)調(diào) Groovy 只是 Java 的一個(gè)變體。您已經(jīng)看到可以用 Groovy 編寫并使用標(biāo)準(zhǔn)的 Java 程序,。為了最后一次證明這點(diǎn),,在結(jié)束本教程之前,我們將通過(guò) JUnit 利用 Java 對(duì) 將 JUnit 加入 Eclipse 項(xiàng)目為了跟上本節(jié)的示例,,需要將 JUnit 加入到 Eclipse 項(xiàng)目中。首先,,右鍵單擊項(xiàng)目,,選擇 Build Path,然后選擇 Add Libraries,,如圖 14 所示: 圖 14. 將 JUnit 加入到項(xiàng)目的構(gòu)建路徑會(huì)出現(xiàn) Add Library 對(duì)話框,,如圖 15 所示。 圖 15. 從庫(kù)列表中選擇 JUnit選擇 JUnit 并單擊 Next 按鈕,。應(yīng)該會(huì)看到如圖 16 所示的對(duì)話框,。選擇 JUnit3 或 4— 具體選擇哪項(xiàng)全憑自己決定 — 并單擊 Finish 按鈕。 圖 16. 選擇 JUnit 3 或 JUnit 4設(shè)置新的測(cè)試用例現(xiàn)在在項(xiàng)目的類路徑中加入了 JUnit,,所以能夠編寫 JUnit 測(cè)試了,。請(qǐng)右鍵單擊 java 源文件夾,選擇 New,,然后選擇 JUnit Test Case,。定義一個(gè)包,給測(cè)試用例命名(例如 請(qǐng)注意,,可以選擇用 Groovy 定義的 圖 17.找到 Song 類選擇該類并單擊 OK(應(yīng)該會(huì)看到與圖 18 類似的對(duì)話框)并在 New JUnit Test Case 對(duì)話框中單擊 Finish 按鈕。 圖 18. Song 的新測(cè)試用例定義測(cè)試方法我選擇使用 JUnit 4,;所以我定義了一個(gè)名為 package org.acme.groovy; import org.junit.Test; public class SongTest { @Test public void testToString(){} } 測(cè)試 toString顯然,需要驗(yàn)證 在創(chuàng)建用于測(cè)試的 圖 19. 所有的 setter 和 getterGroovy 的功勞如果回憶一下,,就會(huì)記得我在本教程開始的時(shí)候說(shuō)過(guò): 因?yàn)?Java 中的每個(gè)對(duì)象都擴(kuò)展自 現(xiàn)在回想一下,,在定義 修正返回類型為了增添樂(lè)趣,,請(qǐng)打開 Groovy package org.acme.groovy class Song { def name String artist def genre String toString(){ "${name}, ${artist}, ${getGenre()}" } def getGenre(){ genre?.toUpperCase() } } 現(xiàn)在,回到 JUnit 測(cè)試,,在 在圖 20 中(以及您自己的代碼中,如果一直跟隨本教程的話),, 圖 20. String,而不是 object始終是普通的 Java返回來(lái)編寫測(cè)試,,另外請(qǐng)注意,,默認(rèn)情況下 Groovy 編譯的類屬性是私有的,所以不能直接在 Java 中訪問(wèn)它們,,必須像下面這樣使用 setter: @Test public void testToString(){ Song sng = new Song(); sng.setArtist("Village People"); sng.setName("Y.M.C.A"); sng.setGenre("Disco"); Assert.assertEquals("Y.M.C.A, Village People, DISCO", sng.toString()); } 編寫這個(gè)測(cè)試用例余下的代碼就是小菜一碟了,。測(cè)試用例很好地演示了這樣一點(diǎn):用 Groovy 所做的一切都可以輕易地在 Java 程序中重用,反之亦然,。用 Java 語(yǔ)言執(zhí)行的一切操作和編寫的一切代碼,,在 Groovy 中也都可以使用。 結(jié)束語(yǔ)如果說(shuō)您從本教程獲得了一個(gè)收獲的話(除了初次體驗(yàn) Groovy 編程之外),,那么這個(gè)收獲應(yīng)該是深入地認(rèn)識(shí)到 Groovy 就是 Java,,只是缺少了您過(guò)去使用的許多語(yǔ)法規(guī)則,。Groovy 是沒有類型、沒有修改符,、沒有 return,、沒有 但是在幕后,,Groovy 就是 Java。 我希望通向精通 Groovy 的這第一段旅程給您帶來(lái)了快樂(lè),。您學(xué)習(xí)了 Groovy 語(yǔ)法,,創(chuàng)建了幾個(gè)能夠體驗(yàn)到 Groovy 的生產(chǎn)力增強(qiáng)功能的類,看到了用 Java 測(cè)試 Groovy 類有多容易,。還遇到了第一次使用 Groovy 的開發(fā)者常見的一些問(wèn)題,,看到了如何在不引起太多麻煩的情況下解決它們。 盡管您可能覺得自己目前對(duì) Groovy 還不是很熟練,,但您已經(jīng)走出了第一步,。您可以用目前學(xué)到的知識(shí)編寫自己的第一個(gè) Groovy 程序 — 畢竟,您已經(jīng)設(shè)置好了同時(shí)支持 Groovy 和 Java 編程的雙重環(huán)境,!作為有趣的練習(xí),,您可以試試用 Gant 設(shè)置下一個(gè)的自動(dòng)構(gòu)建版本,Gant 是基于 Ant 的構(gòu)建工具,,使用 Groovy 來(lái)定義構(gòu)建,,而不是使用 XML。當(dāng)您對(duì) Groovy 更加適應(yīng)時(shí),,可以試著用 Groovy on Grails 構(gòu)建 Web 應(yīng)用程序模塊 — 順便說(shuō)一下,,這是下一篇教程的主題。 |
|