久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

精通 Groovy

 dinghj 2014-11-28

在 IBM Bluemix 云平臺(tái)上開發(fā)并部署您的下一個(gè)應(yīng)用。

現(xiàn)在就開始免費(fèi)試用

開始之前

了解本教程的主要內(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)的配置如下:

  • 支持 Sun JDK 1.5.0_09(或更高版本)或 IBM JDK 1.5.0 SR3 的系統(tǒng),,擁有至少 500 MB 主內(nèi)存
  • 至少 20 MB 可用硬盤空間,用來(lái)安裝本教程涉及的軟件組件和示例

本教程的操作說(shuō)明和示例均基于 Microsoft Windows 操作系統(tǒng),。本教程涉及的所有工具在 Linux 和 Unix 系統(tǒng)上也能工作,。

回頁(yè)首

關(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 的松散的 Java 語(yǔ)法允許省略分號(hào)和修改符,。
  • 除非另行指定,Groovy 的所有內(nèi)容都為 public,。
  • Groovy 允許定義簡(jiǎn)單腳本,,同時(shí)無(wú)需定義正規(guī)的 class 對(duì)象。
  • Groovy 在普通的常用 Java 對(duì)象上增加了一些獨(dú)特的方法和快捷方式,,使得它們更容易使用,。
  • Groovy 語(yǔ)法還允許省略變量類型。

Groovy 的新增特性

雖然 Groovy 允許省略 Java 語(yǔ)法中的一些元素,,但也增加了一些新特性,,例如本地集合、內(nèi)置的正則表達(dá)式和閉包,。在標(biāo)準(zhǔn)的 Java 代碼中,,如果想要?jiǎng)?chuàng)建一個(gè)項(xiàng)列表,首先要導(dǎo)入 java.util.ArrayList,,然后程序化地初始化 ArrayList 實(shí)例,,然后 再向?qū)嵗刑砑禹?xiàng)。在 Groovy 中,,列表和映射都內(nèi)置在語(yǔ)法中 — 無(wú)需導(dǎo)入任何內(nèi)容,。正則表達(dá)式也不需要額外的導(dǎo)入或?qū)ο螅凰鼈兛梢酝ㄟ^(guò)特殊的 Groovy 語(yǔ)法來(lái)創(chuàng)建,。

關(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 之后,,就有可能再也不需要編寫 Iterator 實(shí)例了,。

動(dòng)態(tài)的 Groovy

從技術(shù)上講,Groovy 可能是您最近聽說(shuō)過(guò)的類型最松散的動(dòng)態(tài)語(yǔ)言之一,。從這個(gè)角度講,,Groovy 與 Java 語(yǔ)言的區(qū)別很大,Java 語(yǔ)言是一種固定類型語(yǔ)言,。在 Groovy 中,,類型是可選的,所以您不必輸入 String myStr = "Hello"; 來(lái)聲明 String 變量,。

除此之外,,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 或普通的 java.io.File 實(shí)例變得非常輕松,。

一體兩面

用 Groovy 編寫的任何內(nèi)容都可以編譯成標(biāo)準(zhǔn)的 Java 類文件并在 Java 代碼中重用,。類似地,用標(biāo)準(zhǔn) Java 代碼編寫的內(nèi)容也可以在 Groovy 中重用,。所以,,可以輕易地使用 Groovy 為 Java 代碼編寫單元測(cè)試。而且,,如果用 Groovy 編寫一個(gè)方便的小工具,,那么也可以在 Java 程序中使用這個(gè)小工具。

回頁(yè)首

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)單的 HelloWorld 類中,,我省略了包,而且向控制臺(tái)輸出的時(shí)候沒有使用任何多余的編碼約定,。下一步是用 javac 編譯這個(gè)類,,如下所示:

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 允許輸入 println,,而無(wú)需輸入 System.out.println,。當(dāng)您輸入 println 時(shí),Groovy 會(huì)非常聰明地知道您指的是 System.out,。

所以,,用 Groovy 編寫 Hello World 程序就如下面這樣簡(jiǎn)單:

println "Hello World!"

請(qǐng)注意,在這段代碼周圍沒有類結(jié)構(gòu),,而且也沒有方法結(jié)構(gòu),!我還使用 println 代替了 System.out.println

運(yùn)行 Groovy 示例

假設(shè)我將代碼保存在文件 MyFirstExample.groovy 內(nèi),,只要輸入以下代碼就能運(yùn)行這個(gè)示例:

c:>groovy MyFirstExample.groovy

在控制臺(tái)上輸出 “Hello World!” 所需的工作就這么多,。

快捷方式應(yīng)用

您可能注意到了,我不必編譯 .groovy 文件,。這是因?yàn)?Groovy 屬于腳本語(yǔ)言。腳本語(yǔ)言的一個(gè)特點(diǎn)就是能夠在運(yùn)行時(shí)進(jìn)行解釋,。(在 Java 中,,要從源代碼編譯生成字節(jié)碼,然后才能進(jìn)行解釋,。區(qū)別在于腳本語(yǔ)言能夠直接 解釋源代碼,。)

Groovy 允許完全省略編譯步驟,不過(guò)仍然可以 進(jìn)行編譯,。如果想要編譯代碼,,可以使用 Groovy 編譯器 groovyc。用 groovyc 編譯 Groovy 代碼會(huì)產(chǎn)生標(biāo)準(zhǔn)的 Java 字節(jié)碼,,然后可以通過(guò) java 命令運(yùn)行生成的字節(jié)碼,。這是 Groovy 的一項(xiàng)經(jīng)常被忽略的關(guān)鍵特性:用 Groovy 編寫的所有代碼都能夠通過(guò)標(biāo)準(zhǔn) Java 運(yùn)行時(shí)編譯和運(yùn)行。

至于運(yùn)行代碼,,如果我希望更加簡(jiǎn)潔,,我甚至還能輸入

c:>groovy -e "println 'Hello World!'"

這會(huì)生成相同的結(jié)果,而且甚至無(wú)需定義任何文件,!

回頁(yè)首

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ì)話框
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
確保為新的遠(yuǎn)程站點(diǎn)提供了正確的 URL

輸入 “Groovy plugin” 作為名稱,輸入 “http://dist./groovy/distributions/update/” 作為位置,,單擊 OK 按鈕,,在隨后出現(xiàn)的 Sites to include in search 框中確保選中了名為 “Groovy plugin” 的項(xiàng)目 — 現(xiàn)在的列表應(yīng)該如圖 3 所示。

圖 3.Eclipse 中的遠(yuǎn)程網(wǎng)站清單
Eclipse 中的遠(yuǎn)程網(wǎng)站清單

完成安裝

單擊 Finish 按鈕之后,,應(yīng)該會(huì)出現(xiàn) Search Results 對(duì)話框,。請(qǐng)?jiān)俅未_定選中了 “Groovy plugin” 框并單擊 Next 按鈕,這一步驟如圖 4 所示:

圖 4. 選擇 Groovy 插件
選擇 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
兩個(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 特性
在 Eclipse 中添加 Groovy 特性

創(chuàng)建 Groovy 類

創(chuàng)建 Groovy 類很簡(jiǎn)單。選擇 groovy 文件夾并右鍵單擊它,。選擇 New,,然后選擇 Other,如圖 7 所示:

圖 7. 通過(guò) New 菜單創(chuàng)建 Groovy 類
通過(guò) New 菜單創(chuàng)建 Groovy 類

給類命名

在這里,,找到 Groovy 文件夾,,并選擇 Groovy Class— 應(yīng)該會(huì)看到一個(gè)對(duì)話框,如圖 8 所示,。

圖 8.選擇創(chuàng)建 Groovy 類
選擇創(chuàng)建 Groovy 類

單擊 Next 按鈕,,系統(tǒng)將要求您提供類的名稱。輸入 HelloWorld,。

現(xiàn)在可以將 HelloWorld Groovy 類保留在默認(rèn)包內(nèi),,如圖 9 所示。

圖 9. 現(xiàn)在不必考慮包的問(wèn)題,!
現(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 HelloWorld 示例驚人地相似。但是請(qǐng)注意,,它不包含 public 修改符,。而且,如果仔細(xì)查看 main 方法的參數(shù),,會(huì)注意到它沒有類型,。

編譯程序

現(xiàn)在在 main 方法內(nèi)加入 println "Hello World",完成后的代碼看起來(lái)如下所示:

class HelloWorld {
 static void main(args) {
   println "Hello World"	
 }
}

在源代碼編輯器中應(yīng)該能夠右鍵單擊,,并選擇 Compile Groovy File 選項(xiàng),,如圖 10 所示,。

圖 10. 右鍵單擊 Groovy 文件即可進(jìn)行編譯
右鍵單擊 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
輸出的 Hello World

學(xué)到了什么,?

OK,那么這是一種突出重點(diǎn)的取巧方式,。Groovy 實(shí)際上就是 Java,。其語(yǔ)法不同 — 多數(shù)情況下會(huì)短一些 — 但 Groovy 代碼 100% 符合 Java 字節(jié)碼標(biāo)準(zhǔn),。下一節(jié)將進(jìn)一步介紹這兩種語(yǔ)言的交叉。

回頁(yè)首

Groovy 變身為 Java

前面已經(jīng)看到 Groovy 與 Java 代碼實(shí)際上可以互換的第一個(gè)證據(jù),。這一節(jié)將進(jìn)一步證明這點(diǎn),,繼續(xù)使用 Groovy 構(gòu)建的 HelloWorld 類。

Hello, Java!

為了使您確信 Groovy 就是 Java,,現(xiàn)在在 HelloWorld 類聲明和方法聲明前面加上 public 修改符,,如下所示:

public class HelloWorld {
 public static void main(args) {
  println "Hello World"
 }
}

還不確信?

這個(gè)代碼運(yùn)行起來(lái)同前面的代碼完全一樣,。但是,,如果仍不確信,還可以在 args 參數(shù)前加上 String[]

public class HelloWorld {
 public static void main(String[]args) {
  println "Hello World"
 }
}

現(xiàn)在還沒完

現(xiàn)在,,還可以將 println 替換為 System.out.println— 而且不要忘記加上括號(hào),。

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 的 HelloWorld 類沒有任何 public 修改符,沒有任何類型(沒有 String[]),,而且提供了沒有括號(hào)的 println 快捷方式,。

Hello, Groovy!

如果喜歡,可以將這個(gè)過(guò)程完全翻轉(zhuǎn)過(guò)來(lái),,回到基于 Java 的 Hello World 示例,,刪除文件里的所有內(nèi)容,只保留 System.out 行,,然后在這行刪除 System.out 和括號(hào),。最后只剩下:

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ì)于 Main 類,單擊 Search 按鈕,,找到 HelloWorld 類,。請(qǐng)注意,單詞 class 表明 Eclipse Groovy 插件已經(jīng)將 .groovy 文件編譯為 .class 文件,。

在圖 12 中可以看到整個(gè)這個(gè)過(guò)程 — 如果以前在 Eclipse 中運(yùn)行過(guò) Java 類,,那么您應(yīng)該對(duì)這個(gè)過(guò)程很熟悉,。

圖 12. Groovy 代碼完全符合 Java 字節(jié)碼標(biāo)準(zhǔn)
Groovy 代碼完全符合 Java 字節(jié)碼標(biāo)準(zhǔn)

單擊 Run 按鈕,看到什么了,?實(shí)際上,,“Hello World!” 從未像現(xiàn)在這樣能夠說(shuō)明問(wèn)題。

回頁(yè)首

Groovy 是沒有類型的 Java 代碼

很可能將 Groovy 當(dāng)成是沒有規(guī)則的 Java 代碼,。但實(shí)際上,,Groovy 只是規(guī)則少一些。這一節(jié)的重點(diǎn)是使用 Groovy 編寫 Java 應(yīng)用程序時(shí)可以不用考慮的一個(gè) Java 編程的具體方面:類型定義,。

為什么要有類型定義,?

在 Java 中,如果要聲明一個(gè) String 變量,,則必須輸入:

String value = "Hello World";

但是,,如果仔細(xì)想想,就會(huì)看出,,等號(hào)右側(cè)的字符已經(jīng)表明 value 的類型是 String,。所以,Groovy 允許省略 value 前面的 String 類型變量,,并用 def 代替,。

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)在,,將變量類型 String 替換為 def 并重新運(yùn)行代碼。是不是注意到了相同的結(jié)果,?

除了輸出 message 的值,,還可以用以下調(diào)用輸出它的類型:

def message = "Hello World"
println message.class

輸出 “class java.lang.String” 應(yīng)該是目前為止很受歡迎的一項(xiàng)變化!如果想知道到底發(fā)生了什么,,那么可以告訴您:Groovy 推斷出 message 一定是 String 類型的,,因?yàn)樗闹凳怯秒p引號(hào)括起來(lái)的。

類型推斷的更多內(nèi)容

您可能聽說(shuō)過(guò),,在 Groovy 中 “一切都是對(duì)象” — 但對(duì)于類型來(lái)說(shuō)這句話意味著什么呢,?讓我們看看如果將前面示例中的 String 替換為數(shù)字會(huì)怎么樣,,如下所示:

def message = 12
println message.class

message 變量的數(shù)字值看起來(lái)像是 Java 的原生類型 int,。但是,運(yùn)行這個(gè)代碼就可以看出,,Groovy 將它作為 Integer,。這是因?yàn)樵?Groovy 中 “一切都是對(duì)象”,。

Java 中的所有對(duì)象都擴(kuò)展自 java.lang.Object,這對(duì) Groovy 來(lái)說(shuō)非常方便,。即使在最糟的情況下,,Groovy 運(yùn)行時(shí)不能確定變量的類型,它只需將變量當(dāng)成 Object,,問(wèn)題就解決了,。

繼續(xù)使用這段代碼。將 message 改成自己喜歡的任意類型:Groovy 會(huì)在運(yùn)行時(shí)盡其所能推斷出這個(gè)變量的類型,。

無(wú)類型有什么意義

那么,,Groovy 缺少類型意味著所需的輸入更少。不可否認(rèn),,將 String 替換成 def 并沒有真正節(jié)約多少打字工作 — 三個(gè)字母并不值得如何夸耀,!但是在更高的層次上看,在編寫大量不僅僅包含變量聲明的代碼的時(shí)候,,沒有類型確實(shí)減少了許多打字工作,。更重要的是,這意味著要閱讀的代碼要少得多,。最后,,Groovy 缺少類型能夠帶來(lái)更高的靈活性 — 不需要接口或抽象類。

所以,,只需要使用 def 關(guān)鍵字就能在方法中聲明一個(gè)獨(dú)立變量,,不需要將 def 關(guān)鍵字作為方法聲明中的參數(shù)。在 for 循環(huán)聲明中也不需要它,,這意味著不用編寫 (int x = 0; x < 5; x++),,相反,可以省略 int,,保留空白,。

回頁(yè)首

通過(guò) Groovy 進(jìn)行循環(huán)

同大多數(shù)腳本語(yǔ)言一樣,Groovy 經(jīng)常被宣傳為生產(chǎn)力更高 的 Java 語(yǔ)言替代品,。您已經(jīng)看到了 Groovy 缺少類型能夠如何減少打字工作,。在這一節(jié),將創(chuàng)建并試用一個(gè) repeat 函數(shù),。在這個(gè)過(guò)程中,,將進(jìn)一步探索 Groovy 提高效率的方式。

更好,、更短的循環(huán)

下面這種方法可以更好地感受 Groovy 缺乏類型的好處:首先,,用與創(chuàng)建 HelloWorld 相同的方式創(chuàng)建一個(gè) Groovy 類,將這個(gè)類稱為 MethodMadness,并刪除自動(dòng)生成的類體:將要定義一個(gè)獨(dú)立的 repeat 函數(shù)?,F(xiàn)在在控制臺(tái)中輸入以下代碼:

def repeat(val){
 for(i = 0; i < 5; i++){
  println val
 }
}

起初,,從 Java 的角度來(lái)看,這個(gè)小函數(shù)看起來(lái)可能有些怪(實(shí)際上,,它很像 JavaScript),。但它就是 Java 代碼,只不過(guò)是用 Groovy 的樣式編寫的,。

深入方法

repeat 函數(shù)接受一個(gè)變量 val,。請(qǐng)注意參數(shù)不需要 def。方法體本質(zhì)上就是一個(gè) for 循環(huán),。

調(diào)用這個(gè)函數(shù),。

repeat("hello
  world")

會(huì)輸出 “hello world” 五次。請(qǐng)注意,,for 循環(huán)中省略了 int,。沒有變量類型的 for 循環(huán)要比標(biāo)準(zhǔn)的 Java 代碼短些。現(xiàn)在看看如果在代碼里加入范圍會(huì)出現(xiàn)什么情況,。

Groovy 中的范圍

范圍 是一系列的值,。例如 “0..4” 表明包含 整數(shù) 0、1,、2,、3、4,。Groovy 還支持排除范圍,,“0..<4” 表示 0、1,、2,、3。還可以創(chuàng)建字符范圍:“a..e” 相當(dāng)于 a,、b,、c、d,、e,。“a..<e” 包括小于 e 的所有值,。

循環(huán)范圍

范圍為循環(huán)帶來(lái)了很大的方便,。例如,前面從 0 遞增到 4 的 for 循環(huán)如下所示:

for(i = 0; i < 5; i++)

范圍可以將這個(gè) for 循環(huán)變得更簡(jiǎn)潔,,更易閱讀:

def repeat(val){
 for(i in 0..5){
  println val
 }
}

設(shè)置范圍

如果運(yùn)行這個(gè)示例,,可能會(huì)注意到一個(gè)小問(wèn)題:“Hello World” 輸出了六次而不是五次,。這個(gè)問(wèn)題有三種解決方法:

  • 將包含的范圍限制到 4:
    for(i in 0..4)
  • 從 1 而不是 0 開始:
    def repeat(val){
     for(i in 1..5){
      println val
     }
    }
  • 將范圍由包含改為排除:
    def repeat(val){
     for(i in 0..<5){
      println val
     }
    }

不論采用哪種方法,都會(huì)得到原來(lái)的效果 — 輸出 “Hello World” 五次,。

默認(rèn)參數(shù)值

現(xiàn)在已經(jīng)成功地使用 Groovy 的范圍表達(dá)式縮短了 repeat 函數(shù)。但這個(gè)函數(shù)依然有些限制,。如果想重復(fù) “Hello World” 八次該怎么辦,?如果想對(duì)不同的值重復(fù)不同次數(shù) — 比如 “Hello World” 重復(fù)八次,“Goodbye Sunshine” 重復(fù)兩次,,這時(shí)該怎么辦,?

每次調(diào)用 repeat 時(shí)都要指定需要的重復(fù)次數(shù)的做法已經(jīng)過(guò)時(shí)了,特別是在已經(jīng)適應(yīng)了默認(rèn)行為(重復(fù)五次)的時(shí)候,。

Groovy 支持默認(rèn)參數(shù)值,,可以在函數(shù)或方法的正式定義中指定參數(shù)的默認(rèn)值。調(diào)用函數(shù)的程序可以選擇省略參數(shù),,使用默認(rèn)值,。

更加復(fù)雜的參數(shù)值

使用前面的 repeat 函數(shù)時(shí),如果希望調(diào)用程序能夠指定重復(fù)值,,可以像下面這樣編碼:

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ù)),。

回頁(yè)首

Groovy 集合

在 Groovy 提供的所有方便的快捷方式和功能中,,最有幫助的一個(gè)可能就是內(nèi)置的 集合?;叵胍幌略?Java 編程中是如何使用集合的 — 導(dǎo)入 java.util 類,,初始化集合,將項(xiàng)加入集合,。這三個(gè)步驟都會(huì)增加不少代碼,。

而 Groovy 可以直接在語(yǔ)言內(nèi)使用集合。在 Groovy 中,,不需要導(dǎo)入專門的類,,也不需要初始化對(duì)象。集合是語(yǔ)言本身的本地成員,。Groovy 也使集合(或者列表)的操作變得非常容易,,為增加和刪除項(xiàng)提供了直觀的幫助。

可以將范圍當(dāng)作集合

在前一節(jié)學(xué)習(xí)了如何用 Groovy 的范圍將循環(huán)變得更容易,。范圍表達(dá)式 “0..4” 代表數(shù)字的集合— 0,、1、2,、3 和 4,。為了驗(yàn)證這一點(diǎn),,請(qǐng)創(chuàng)建一個(gè)新類,將其命名為 Ranger,。保留類定義和 main 方法定義,。但是這次添加以下代碼:

def range = 0..4
println range.class
assert range instanceof List

請(qǐng)注意,assert 命令用來(lái)證明范圍是 java.util.List 的實(shí)例,。接著運(yùn)行這個(gè)代碼,,證實(shí)該范圍現(xiàn)在是類型 List 的集合。

豐富的支持

Groovy 的集合支持相當(dāng)豐富,,而且美妙之處就在于,,在 Groovy 的魔法背后,一切都是標(biāo)準(zhǔn)的 Java 對(duì)象,。每個(gè) Groovy 集合都是 java.util.Collectionjava.util.Map 的實(shí)例,。

前面提到過(guò),Groovy 的語(yǔ)法提供了本地列表和映射,。例如,,請(qǐng)將以下兩行代碼添加到 Ranger 類中:

def coll = ["Groovy", "Java", "Ruby"]
assert  coll instanceof Collection
assert coll instanceof ArrayList

你將會(huì)注意到,coll 對(duì)象看起來(lái)很像 Java 語(yǔ)言中的數(shù)組,。實(shí)際上,,它是一個(gè) Collection。要在普通的 Java 代碼中得到集合的相同實(shí)例,,必須執(zhí)行以下操作:

Collection<String> coll = new ArrayList<String>();
coll.add("Groovy");
coll.add("Java");
coll.add("Ruby");

在 Java 代碼中,,必須使用 add() 方法向 ArrayList 實(shí)例添加項(xiàng)。

添加項(xiàng)

Groovy 提供了許多方法可以將項(xiàng)添加到列表 — 可以使用 add() 方法(因?yàn)榈讓拥募鲜且粋€(gè)普通的 ArrayList 類型),,但是還有許多快捷方式可以使用,。

例如,下面的每一行代碼都會(huì)向底層集合加入一些項(xiàng):

coll.add("Python")
coll << "Smalltalk"
coll[5] = "Perl"

請(qǐng)注意,,Groovy 支持操作符重載 —<< 操作符被重載,,以支持向集合添加項(xiàng)。還可以通過(guò)位置參數(shù)直接添加項(xiàng),。在這個(gè)示例中,,由于集合中只有四個(gè)項(xiàng),所以 [5] 操作符將 “Perl” 放在最后,。請(qǐng)自行輸出這個(gè)集合并查看效果,。

檢索非常輕松

如果需要從集合中得到某個(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

join()count() 只是在任何項(xiàng)列表上都可以調(diào)用的眾多方便方法中的兩個(gè),。分布操作符(spread operator) 是個(gè)特別方便的工具,使用這個(gè)工具不用在集合上迭代,,就能夠調(diào)用集合的每個(gè)項(xiàng)上的方法,。

假設(shè)有一個(gè) String 列表,,現(xiàn)在想將列表中的項(xiàng)目全部變成大寫,,可以編寫以下代碼:

assert ["JAVA", "GROOVY"] == 
  ["Java", "Groovy"]*.toUpperCase()

請(qǐng)注意 *. 標(biāo)記。對(duì)于以上列表中的每個(gè)值,,都會(huì)調(diào)用 toUpperCase(),,生成的集合中每個(gè) String 實(shí)例都是大寫的。

回頁(yè)首

Groovy 映射

除了豐富的列表處理功能,,Groovy 還提供了堅(jiān)固的映射機(jī)制,。同列表一樣,映射也是本地?cái)?shù)據(jù)結(jié)構(gòu),。而且 Groovy 中的任何映射機(jī)制在幕后都是 java.util.Map 的實(shí)例,。

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è) HashMap 實(shí)例容納兩個(gè)名稱-值對(duì),每一個(gè)都是 String 的實(shí)例,。

通過(guò) Groovy 進(jìn)行映射

Groovy 使得處理映射的操作像處理列表一樣簡(jiǎn)單 — 例如,,可以用 Groovy 將上面的 Java 映射寫成

def hash = [name:"Andy", "VPN-#":45]

請(qǐng)注意,Groovy 映射中的鍵不必是 String,。在這個(gè)示例中,,name 看起來(lái)像一個(gè)變量,但是在幕后,,Groovy 會(huì)將它變成 String,。

全都是 Java

接下來(lái)創(chuàng)建一個(gè)新類 Mapper 并加入上面的代碼。然后添加以下代碼,,以證實(shí)底層的代碼是真正的 Java 代碼:

assert hash.getClass() == java.util.LinkedHashMap

可以看到 Groovy 使用了 Java 的 LinkedHashMap 類型,,這意味著可以使用標(biāo)準(zhǔn)的 Java 一樣語(yǔ)句對(duì) hash 中的項(xiàng)執(zhí)行 putget 操作。

hash.put("id", 23)
assert hash.get("name") == "Andy"

有 groovy 特色的映射

現(xiàn)在您已經(jīng)看到,,Groovy 給任何語(yǔ)句都施加了魔法,,所以可以用 . 符號(hào)將項(xiàng)放入映射中,。如果想將新的名稱-值對(duì)加入映射(例如 dob 和 “01/29/76”),可以像下面這樣操作:

hash.dob = "01/29/76"

. 符號(hào)還可以用來(lái)獲取項(xiàng),。例如,,使用以下方法可以獲取 dob 的值:

assert hash.dob == "01/29/76"

當(dāng)然 . 要比調(diào)用 get() 方法更具 Groovy 特色。

位置映射

還可以使用假的位置語(yǔ)法將項(xiàng)放入映射,,或者從映射獲取項(xiàng)目,,如下所示:

assert hash["name"] == "Andy"
hash["gender"] = "male"
assert hash.gender == "male"
assert hash["gender"] == "male"

但是,請(qǐng)注意,,在使用 [] 語(yǔ)法從映射獲取項(xiàng)時(shí),,必須將項(xiàng)作為 String 引用。

回頁(yè)首

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 的 Iterator 實(shí)例,用它在集合上迭代,,就像下面這樣:

def acoll = ["Groovy", "Java", "Ruby"]
		
for(Iterator iter = acoll.iterator(); iter.hasNext();){
 println iter.next()
}

實(shí)際上在 for 循環(huán)中并不需要類型聲明,,因?yàn)?Groovy 已經(jīng)將迭代轉(zhuǎn)變?yōu)槿魏渭系闹苯映蓡T。在這個(gè)示例中,,不必獲取 Iterator 實(shí)例并直接操縱它,,可以直接在集合上迭代。而且,,通常放在循環(huán)構(gòu)造內(nèi)的行為(例如 for 循環(huán)體中 println)接下來(lái)要放在閉包內(nèi),。在深入之前,先看看如何執(zhí)行這步操作,。

能否看見閉包,?

對(duì)于上面的代碼,可以用更簡(jiǎn)潔的方式對(duì)集合進(jìn)行迭代,,如下所示:

def acoll = ["Groovy", "Java", "Ruby"]
		
acoll.each{
 println it
}

請(qǐng)注意,,each 直接在 acoll 實(shí)例內(nèi)調(diào)用,,而 acoll 實(shí)例的類型是 ArrayList。在 each 調(diào)用之后,,引入了一種新的語(yǔ)法 —{,,然后是一些代碼,然后是 },。由 {} 包圍起來(lái)的代碼塊就是閉包,。

執(zhí)行代碼

閉包是可執(zhí)行的代碼塊。它們不需要名稱,,可以在定義之后執(zhí)行,。所以,在上面的示例中,,包含輸出 it(后面將簡(jiǎn)單解釋 it)的行為的無(wú)名閉包將會(huì)在 acoll 集合類型中的每個(gè)值上被調(diào)用,。

在較高層面上,{} 中的代碼會(huì)執(zhí)行三次,,從而生成如圖 13 所示的輸出,。

圖 13. 迭代從未像現(xiàn)在這樣容易
迭代從未像現(xiàn)在這樣容易

閉包中的 it 變量是一個(gè)關(guān)鍵字,,指向被調(diào)用的外部集合的每個(gè)值 — 它是默認(rèn)值,,可以用傳遞給閉包的參數(shù)覆蓋它。下面的代碼執(zhí)行同樣的操作,,但使用自己的項(xiàng)變量:

def acoll = ["Groovy", "Java", "Ruby"]
		
acoll.each{ value ->
 println value
}

在這個(gè)示例中,,用 value 代替了 Groovy 的默認(rèn) it

迭代無(wú)處不在

閉包在 Groovy 中頻繁出現(xiàn),,但是,,通常用于在一系列值上迭代的時(shí)候。請(qǐng)記住,,一系列值可以用多種方式表示,,不僅可以用列表表示 — 例如,可以在映射,、String,、JDBC RowsetFile 的行上迭代,,等等,。

如果想在前面一節(jié) “Groovy 中的映射” 中的 hash 對(duì)象上迭代,可以編寫以下代碼:

def hash = [name:"Andy", "VPN-#":45]
hash.each{ key, value ->
 println "${key} : ${value}"
}

請(qǐng)注意,,閉包還允許使用多個(gè)參數(shù) — 在這個(gè)示例中,,上面的代碼包含兩個(gè)參數(shù)(keyvalue)。

使用 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è) ClosureExample 對(duì)象,,并保持它提供的默認(rèn)類語(yǔ)法,。在生成的 main() 方法中,添加以下代碼:

def excite = { word ->
 return "${word}!!"
}

這段代碼是名為 excite 的閉包,。這個(gè)閉包接受一個(gè)參數(shù)(名為 word),,返回的 Stringword 變量加兩個(gè)感嘆號(hào)。請(qǐng)注意在 String 實(shí)例中替換 的用法,。在 String 中使用 ${value}語(yǔ)法將告訴 Groovy 替換 String 中的某個(gè)變量的值,。可以將這個(gè)語(yǔ)法當(dāng)成 return word + "!!" 的快捷方式,。

延遲執(zhí)行

既然有了閉包,,下面就該實(shí)際使用它了??梢酝ㄟ^(guò)兩種方法調(diào)用閉包:直接調(diào)用或者通過(guò) call() 方法調(diào)用,。

繼續(xù)使用 ClosureExample 類,在閉包定義下面添加以下兩行代碼:

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ì)感到驚訝了吧,?

回頁(yè)首

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è)示例就是在不同類的 main() 方法中,。而且,,您已經(jīng)知道,在 Groovy 中可以像在 Java 代碼中一樣定義類,。惟一的區(qū)別是,,不需要使用 public 修改符,而且還可以省略方法參數(shù)的類型,。這一節(jié)將介紹使用 Groovy 類能夠進(jìn)行的其他所有操作,。

Song 類

我們先從用 Groovy 定義一個(gè)簡(jiǎn)單的 JavaBean 形式的類開始,這個(gè)類稱為 Song,。

第一步自然是用 Groovy 創(chuàng)建名為 Song 的類,。這次還要為它創(chuàng)建一個(gè)包結(jié)構(gòu) — 創(chuàng)建一個(gè)包名,例如 org.acme.groovy,。

創(chuàng)建這個(gè)類之后,,刪除 Groovy 插件自動(dòng)生成的 main()

歌曲有一些屬性 — 創(chuàng)作歌曲的藝術(shù)家,、歌曲名稱,、風(fēng)格等等。請(qǐng)將這些屬性加入新建的 Song 類,,如下所示:

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 .class,。還記得如何用 Groovy 創(chuàng)建 HelloWorld 類,、找到 .class 文件并運(yùn)行它么?也可以用新定義的 Song 類完成同樣的操作,。如果通過(guò) Groovy 的 groovyc 編譯器編譯代碼(Eclipse Groovy 插件已經(jīng)這樣做了),,就會(huì)生成一個(gè) Song.class 文件。

這意味著,,如果想在另一個(gè) Groovy 類或 Java 類中使用新建的 Song 類,,則必須導(dǎo)入 它(當(dāng)然,除非使用 Song 的代碼與 Song 在同一個(gè)包內(nèi)),。

接下來(lái)創(chuàng)建一個(gè)新類,,名為 SongExample,將其放在另一個(gè)包結(jié)構(gòu)內(nèi),,假設(shè)是 org.thirdparty.lib,。

現(xiàn)在應(yīng)該看到如下所示的代碼:

package org.thirdparty.lib

class SongExample {
 static void main(args) {}
}

類的關(guān)系

現(xiàn)在是使用 Song 類的時(shí)候了,。首先導(dǎo)入實(shí)例,并將下面的代碼添加到 SongExamplemain() 方法中,。

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)在 Song 實(shí)例創(chuàng)建完成了,!但是仔細(xì)看看以前定義的 Song 類的初始化代碼,是否注意到什么特殊之處,?您應(yīng)該注意到自動(dòng)生成了構(gòu)造函數(shù),。

類初始化

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ò) . 語(yǔ)法間接地訪問(wèn)屬性,。而且,Groovy 還生成了標(biāo)準(zhǔn)的 setter 和 getter 方法,。

在進(jìn)行屬性操縱時(shí),,非常有 Groovy 特色的是:總是會(huì)調(diào)用 setter 和 getter 方法 — 即使直接通過(guò) . 語(yǔ)法訪問(wèn)屬性也是如此。

核心的靈活性

Groovy 是一種本質(zhì)上就很靈活的語(yǔ)言,。例如,,看看從前面的代碼中將 setGenre() 方法調(diào)用的括號(hào)刪除之后會(huì)怎么樣,如下所示:

sng3.setGenre "Disco"
assert sng3.genre == "Disco"

在 Groovy 中,,對(duì)于接受參數(shù)的方法,,可以省略括號(hào) — 在某些方面,這樣做會(huì)讓代碼更容易閱讀,。

方法覆蓋

迄今為止已經(jīng)成功地創(chuàng)建了 Song 類的一些實(shí)例,。但是,它們還沒有做什么有趣的事情,??梢杂靡韵旅钶敵鲆粋€(gè)實(shí)例:

println sng3

在 Java 中這樣只會(huì)輸出所有對(duì)象的默認(rèn) toString() 實(shí)現(xiàn),也就是類名和它的 hashcode(即 org.acme.groovy.Song@44f787),。下面來(lái)看看如何覆蓋默認(rèn)的 toString() 實(shí)現(xiàn),,讓輸出效果更好。

Song 類中,添加以下代碼:

String toString(){
 "${name}, ${artist}, ${genre}"
}

根據(jù)本教程已經(jīng)學(xué)到的內(nèi)容,,可以省略 toString() 方法上的 public 修改符,。仍然需要指定返回類型(String),以便實(shí)際地覆蓋正確的方法,。方法體的定義很簡(jiǎn)潔 — 但 return 語(yǔ)句在哪,?

不需要 return

您可能已經(jīng)想到:在 Groovy 中可以省略 return 語(yǔ)句。Groovy 默認(rèn)返回方法的最后一行,。所以在這個(gè)示例中,,返回包含類屬性的 String

重新運(yùn)行 SongExample 類,,應(yīng)該會(huì)看到更有趣的內(nèi)容,。toString() 方法返回一個(gè)描述,而不是 hashcode,。

特殊訪問(wèn)

Groovy 的自動(dòng)生成功能對(duì)于一些功能來(lái)說(shuō)很方便,,但有些時(shí)候需要覆蓋默認(rèn)的行為。例如,,假設(shè)需要覆蓋 Song 類中 getGenre() 方法,,讓返回的 String 全部為大寫形式。

提供這個(gè)新行為很容易,,只要定義 getGenre() 方法即可,。可以讓方法的聲明返回 String,,也可以完全省略它(如果愿意),。下面的操作可能是最簡(jiǎn)單的:

def getGenre(){
 genre.toUpperCase()
}

同以前一樣,這個(gè)簡(jiǎn)單方法省略了返回類型和 return 語(yǔ)句?,F(xiàn)在再次運(yùn)行 SongExample 類,。應(yīng)該會(huì)看到一些意外的事情 —— 出現(xiàn)了空指針異常。

空指針安全性

如果您一直在跟隨本教程,,那么應(yīng)該已經(jīng)在 SongExample 類中加入了下面的代碼:

assert sng3.genre == "Disco"

結(jié)果在重新運(yùn)行 SongExample 時(shí)出現(xiàn)了斷言錯(cuò)誤 — 這正是為什么在 Eclipse 控制臺(tái)上輸出了丑陋的紅色文字,。(很抱歉使用了這么一個(gè)糟糕的技巧)

幸運(yùn)的是,可以輕松地修復(fù)這個(gè)錯(cuò)誤:只要在 SongExample 類中添加以下代碼:

println sng2.artist.toUpperCase()

但是現(xiàn)在控制臺(tái)上出現(xiàn)了更多的 紅色文本 — 出什么事了,?!

可惡的 null

如果回憶一下,,就會(huì)想起 sng2 實(shí)例沒有定義 artist 值,。所以,在調(diào)用 toUpperCase() 方法時(shí)就會(huì)生成 Nullpointer 異常,。

幸運(yùn)的是,, Groovy 通過(guò) 操作符提供了一個(gè)安全網(wǎng) — 在方法調(diào)用前面添加一個(gè) 就相當(dāng)于在調(diào)用前面放了一個(gè)條件,可以防止在 null 對(duì)象上調(diào)用方法。

例如,,將 sng2.artist.toUpperCase() 行替換成 sng2.artist?.toUpperCase(),。請(qǐng)注意,也可以省略后面的括號(hào),。(Groovy 實(shí)際上也允許在不帶參數(shù)的方法上省略括號(hào),。不過(guò),如果 Groovy 認(rèn)為您要訪問(wèn)類的屬性而不是方法,,那么這樣做可能會(huì)造成問(wèn)題,。)

重新運(yùn)行 SongExample 類,您會(huì)發(fā)現(xiàn) 操作符很有用,。在這個(gè)示例中,,沒有出現(xiàn)可惡的異常?,F(xiàn)在將下面的代碼放在這個(gè)類內(nèi),,再次運(yùn)行代碼。

def sng4 = new Song(name:"Thriller", artist:"Michael Jackson")
println sng4

就是 Java

您將會(huì)注意到,,雖然預(yù)期可能有異常,,但是沒有生成異常。即使沒有定義 genre,,getGenre() 方法也會(huì)調(diào)用 toUpperCase(),。

您還記得 Groovy 就是 Java,對(duì)吧,?所以在 SongtoString() 中,,引用了 genre 屬性本身,所以不會(huì)調(diào)用 getGenre()?,F(xiàn)在更改 toString() 方法以使用 getGenre(),,然后再看看程序運(yùn)行的結(jié)果。

String toString(){
 "${name}, ${artist}, ${getGenre()}"
}

重新運(yùn)行 SongExample,,出現(xiàn)類似的異?!,F(xiàn)在,,請(qǐng)自己嘗試修復(fù)這個(gè)問(wèn)題,,看看會(huì)發(fā)生什么。

另一個(gè)方便的小操作符

希望您做的修改與我的類似,。在下面將會(huì)看到,,我進(jìn)一步擴(kuò)充了 Song 類的 getGenre() 方法,以利用 Groovy 中方便的 操作符,。

def getGenre(){
 genre?.toUpperCase()
}

操作符時(shí)刻都非常有用,,可以極大地減少條件語(yǔ)句,。

回頁(yè)首

對(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ì) Song 類進(jìn)行單元測(cè)試,。

將 JUnit 加入 Eclipse 項(xiàng)目

為了跟上本節(jié)的示例,,需要將 JUnit 加入到 Eclipse 項(xiàng)目中。首先,,右鍵單擊項(xiàng)目,,選擇 Build Path,然后選擇 Add Libraries,,如圖 14 所示:

圖 14. 將 JUnit 加入到項(xiàng)目的構(gòu)建路徑
簡(jiǎn)單的項(xiàng)目目錄結(jié)構(gòu)

會(huì)出現(xiàn) Add Library 對(duì)話框,,如圖 15 所示。

圖 15. 從庫(kù)列表中選擇 JUnit
簡(jiǎn)單的項(xiàng)目目錄結(jié)構(gòu)

選擇 JUnit 并單擊 Next 按鈕,。應(yīng)該會(huì)看到如圖 16 所示的對(duì)話框,。選擇 JUnit34— 具體選擇哪項(xiàng)全憑自己決定 — 并單擊 Finish 按鈕。

圖 16. 選擇 JUnit 3 或 JUnit 4
簡(jiǎn)單的項(xiàng)目目錄結(jié)構(gòu)

設(shè)置新的測(cè)試用例

現(xiàn)在在項(xiàng)目的類路徑中加入了 JUnit,,所以能夠編寫 JUnit 測(cè)試了,。請(qǐng)右鍵單擊 java 源文件夾,選擇 New,,然后選擇 JUnit Test Case,。定義一個(gè)包,給測(cè)試用例命名(例如 SongTest),,在 Class Under Test 部分,,單擊 Browse 按鈕。

請(qǐng)注意,,可以選擇用 Groovy 定義的 Song 類,。圖 17 演示了這一步驟:

圖 17.找到 Song 類
簡(jiǎn)單的項(xiàng)目目錄結(jié)構(gòu)

選擇該類并單擊 OK(應(yīng)該會(huì)看到與圖 18 類似的對(duì)話框)并在 New JUnit Test Case 對(duì)話框中單擊 Finish 按鈕。

圖 18. Song 的新測(cè)試用例
簡(jiǎn)單的項(xiàng)目目錄結(jié)構(gòu)

定義測(cè)試方法

我選擇使用 JUnit 4,;所以我定義了一個(gè)名為 testToString() 的測(cè)試方法,,如下所示:

package org.acme.groovy;

import org.junit.Test;

public class SongTest {
	
 @Test
 public void testToString(){}

}

測(cè)試 toString

顯然,需要驗(yàn)證 toString() 方法是否沒有問(wèn)題,,那么第一步該做什么呢,?如果想的是 “導(dǎo)入 Song 類”,那么想得就太難了 —Song 類在同一個(gè)包內(nèi),,所以第一步是創(chuàng)建它的實(shí)例,。

在創(chuàng)建用于測(cè)試的 Song 實(shí)例時(shí),請(qǐng)注意不能通過(guò)傳給構(gòu)造函數(shù)的映射完全初始化 — 而且,,如果想自動(dòng)完成實(shí)例的 setter 方法,,可以看到每個(gè) setter 接受的是 Object 而不是 String(如圖 19 所示)。為什么會(huì)這樣呢,?

圖 19. 所有的 setter 和 getter
簡(jiǎn)單的項(xiàng)目目錄結(jié)構(gòu)

Groovy 的功勞

如果回憶一下,,就會(huì)記得我在本教程開始的時(shí)候說(shuō)過(guò):

因?yàn)?Java 中的每個(gè)對(duì)象都擴(kuò)展自 java.lang.Object,所以即使在最壞情況下,,Groovy 不能確定變量的類型,,Groovy 也能將變量的類型設(shè)為 Object然后問(wèn)題就會(huì)迎刃而解。

現(xiàn)在回想一下,,在定義 Song 類時(shí),,省略了每個(gè)屬性的類型。Groovy 將自然地將每個(gè)屬性的類型設(shè)為 Object,。所以,,在標(biāo)準(zhǔn) Java 代碼中使用 Song 類時(shí),看到的 getter 和 setter 的參數(shù)類型和返回類型全都是 Object,。

修正返回類型

為了增添樂(lè)趣,,請(qǐng)打開 Groovy Song 類,將 artist 屬性改為 String 類型,,而不是無(wú)類型,,如下所示:

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è)試,,在 Song 實(shí)例上使用自動(dòng)完成功能 — 看到了什么,?

在圖 20 中(以及您自己的代碼中,如果一直跟隨本教程的話),,setArtist() 方法接受一個(gè) String,,而不是Object。Groovy 再次證明了它就是 Java,,而且應(yīng)用了相同的規(guī)則,。

圖 20. String,而不是 object
簡(jiǎn)單的項(xiàng)目目錄結(jié)構(gòu)

始終是普通的 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 中也都可以使用。

回頁(yè)首

結(jié)束語(yǔ)

如果說(shuō)您從本教程獲得了一個(gè)收獲的話(除了初次體驗(yàn) Groovy 編程之外),,那么這個(gè)收獲應(yīng)該是深入地認(rèn)識(shí)到 Groovy 就是 Java,,只是缺少了您過(guò)去使用的許多語(yǔ)法規(guī)則,。Groovy 是沒有類型、沒有修改符,、沒有 return,、沒有 Iterator、不需要導(dǎo)入集合的 Java,。簡(jiǎn)而言之,,Groovy 就是丟掉了許多包袱的 Java,這些包袱可能會(huì)壓垮 Java 項(xiàng)目,。

但是在幕后,,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ō)一下,,這是下一篇教程的主題。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多