本文適合於不熟悉 Groovy,但想快速輕松地了解其基礎知識的 Java開發人員。了解 Groovy 對 Java 語法的簡化變形,學習 Groovy 的核心功能,例如本地集合、內置正則表達式和閉包。編寫第一個 Groovy 類,然后學習如何使用 JUnit 輕松地進行測試。借助功能完善的 Groovy 開發環境和使用技能,您將輕松完成本教程的學習。最重要的是,您將學會如何在日常 Java 應用程序開發中聯合使用 Groovy 和 Java 代碼。
閱讀本文的前提條件:為了從本教程得到最大收獲,您應該熟悉 Java 語法和在 Java 平台上進行面向對象開發的基本概念。如果熟悉C#的話,基本上也能很快上手。
本文預計時長:30分鍾
一、groovy簡介和環境搭建
本機環境:
ubuntu 14.04 64bit
JDK 1.7.67
IDE : intellij idea 13.1
1、groovy簡介
其官方介紹為,Groovy...
- is an agile and dynamic language for the Java Virtual Machine
- builds upon the strengths of Java but has additional power features inspired by languages like Python, Ruby and Smalltalk
- makes modern programming features available to Java developers with almost-zero learning curve
- provides the ability to statically type check and statically compile your code for robustness and performance
- supports Domain-Specific Languages and other compact syntax so your code becomes easy to read and maintain
- makes writing shell and build scripts easy with its powerful processing primitives, OO abilities and an Ant DSL
- increases developer productivity by reducing scaffolding code when developing web, GUI, database or console applications
- simplifies testing by supporting unit testing and mocking out-of-the-box
- seamlessly integrates with all existing Java classes and libraries
- compiles straight to Java bytecode so you can use it anywhere you can use Java
簡單說來:Groovy是一種運行在JVM上的動態語言,它吸取了Python,Ruby和Smalltalk等語言的優點,在Java語言的基礎之上增加了許多特色功能;對於Java開發人員來說掌握Groovy是沒有什么太大障礙的;相比 Java 而言,語法更易懂,更易上手,更易調試;無縫的集成了Java 的類和庫;編譯后的.groovy也是以class的形式出現的。
2、groovy下載
網址:http://groovy.codehaus.org/Download
目前最新穩定版為Groovy 2.3 (2014-09-14)
這里下載 :
Download zip: Binary Release :groovy-binary-2.3.6.zip
Download documentation: JavaDoc and zipped online documentation :groovy-docs-2.3.6.zip
3、groovy環境配置和Hello World!
1)首先解壓:
unzip groovy-binary-2.3.6.zip #解壓groovy unzip groovy-docs-2.3.6.zip #解壓docs
2) 進入到Groovy Shell命令界面:
amosli@amosli-ThinkPad:~/developsoft/language/groovy/groovy-2.3.6/bin$ ./groovysh Groovy Shell (2.3.6, JVM: 1.7.0_67) Type ':help' or ':h' for help. ------------------------------------------------------------------------------- groovy:000> println "hello world!" hello world! ===> null groovy:000> :h
在Groovy Shell里不必定義class可以直接寫代碼,如下面進行一個for循環:
groovy:000> for(i=0;i<10;i++){ groovy:001> println("i:"+i);} i:0 i:1 i:2 i:3 i:4 i:5 i:6 i:7 i:8 i:9 ===> null
注意這里,你可以發現i是沒有指定int類型的,這里也是寫法上也是比較隨意的。
3)、將groovy加入到環境變量(可選)
將解壓后的groovy拷到/usr/local/groovy 目錄下:
root@amosli-ThinkPad:/usr/local/groovy# cp -r /home/amosli/developsoft/language/groovy/groovy-2.3.6 .
將groovy路徑拷到/etc/profile里:
gedit /etc/profile #使用gedit打開profile,也可以使用vi等工具
將下面內容拷到profile里最后位置:
export GROOVY_HOME=/usr/local/groovy/groovy-2.3.6 export PATH=$GROOVY_HOME/bin:$PATH:. export GROOVY_HOME export PATH
全部的profile內容:

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1)) # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...). if [ "$PS1" ]; then if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then # The file bash.bashrc already sets the default PS1. # PS1='\h:\w\$ ' if [ -f /etc/bash.bashrc ]; then . /etc/bash.bashrc fi else if [ "`id -u`" -eq 0 ]; then PS1='# ' else PS1='$ ' fi fi fi # The default umask is now handled by pam_umask. # See pam_umask(8) and /etc/login.defs. if [ -d /etc/profile.d ]; then for i in /etc/profile.d/*.sh; do if [ -r $i ]; then . $i fi done unset i fi JAVA_HOME=/usr/local/java/jdk1.7.0_67 PATH=$PATH:$HOME/bin:$JAVA_HOME/bin export JAVA_HOME export PATH export GROOVY_HOME=/usr/local/groovy/groovy-2.3.6 export PATH=$GROOVY_HOME/bin:$PATH:. export GROOVY_HOME export PATH
更新環境變量:
source /etc/profile
驗證是否成功:
# groovy -version Groovy Version: 2.3.6 JVM: 1.7.0_67 Vendor: Oracle Corporation OS: Linux
打開groovyConsole:
4)、使用IDE進行開發(這里以Intellij idea 13.1為例)
1. Enable the plugin
Before you create your first Groovy application make sure Groovy plugin is enabled in Settings → Plugins.
2. Create a new project
Open Project Wizard and select Scala template. Since Groovy requires Java you have to specify the Project SDK.
If you create a Groovy project for the first time IntelliJ IDEA will offer you to create Groovy SDK library. Press Create button and choose directory with a Groovy SDK.
The IDE will create an empty project.
3. Create a new class
The easiest way to create Groovy class or script is to use Ctrl + N shortcut from Project View or Navigation Bar.
Choose between class, interface, enum and annotation with Up and Down arrows.
Let's create a class with a method returning "Hello, world!" string.
4. Create a new script
Now we can create a script file via Ctrl + N shortcut.
Choose between script and GroovyDSL script with Up and Down arrows.
Now we can create an instance of our class and invoke hello method.
5. Run the project
In order to run the application you can manually create a Run configuration via Run → Edit configurations or run the active script automatically by pressing Ctrl + Shift + F10 shortcut.
使用Groovy Shell :
打開Tools-->Groovy Shell...
使用Groovy Console :
打開Tools-->Groovy Console...
二、Groovy初探
1、Groovy和Java對比
- Groovy 的松散的 Java 語法允許省略分號和修改符。
- 除非另行指定,Groovy 的所有內容都為
public
。 - Groovy 允許定義簡單腳本,同時無需定義正規的
class
對象。 - Groovy 在普通的常用 Java 對象上增加了一些獨特的方法和快捷方式,使得它們更容易使用。
- Groovy 語法還允許省略變量類型。
- 關於閉包:可以將閉包 想像為一個代碼塊,可以現在定義,以后再執行。可以使用這些強大的構造做許多漂亮的事,不過最著名的是簡化迭代。使用 Groovy 之后,就有可能再也不需要編寫
Iterator
實例了。 -
動態的 Groovy: 從技術上講,Groovy 可能是您最近聽說過的類型最松散的動態語言之一。從這個角度講,Groovy 與 Java 語言的區別很大,Java 語言是一種固定類型語言。在 Groovy 中,類型是可選的,所以您不必輸入
String myStr = "Hello";
來聲明String
變量。可以直接使用def進行不指定類型定義,類似於js中的var。 - 與Java互用:用 Groovy 編寫的任何內容都可以編譯成標准的 Java 類文件並在 Java 代碼中重用。類似地,用標准 Java 代碼編寫的內容也可以在 Groovy 中重用。
2、實例演示Java和Groovy的區別
用 Java 編寫的 Hello World
用 Java 編寫的典型的 Hello World 示例如下所示:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } }
編譯和運行 Java 示例
在這個簡單的 HelloWorld
類中,我省略了包,而且向控制台輸出的時候沒有使用任何多余的編碼約定。下一步是用 javac
編譯這個類,如下所示:
c:>javac HelloWorld.java
最后,運行經過編譯的類:
c:>java HelloWorld
迄今為止還不錯 — 很久以前就會編這么基礎的代碼了,所以這里只是回顧一下。下面,請看用 Groovy 編碼的相同過程。
用 Groovy 編寫的 Hello World
就像前面提到過的,Groovy 支持松散的 Java 語法 — 例如,不需要為打印 “Hello World!” 這樣的簡單操作定義類。
而且,Groovy 使日常的編碼活動變得更容易,例如,Groovy 允許輸入 println
,而無需輸入 System.out.println
。當您輸入 println
時,Groovy 會非常聰明地知道您指的是 System.out
。
所以,用 Groovy 編寫 Hello World 程序就如下面這樣簡單:
println "Hello World!"
請注意,在這段代碼周圍沒有類結構,而且也沒有方法結構!我還使用 println
代替了 System.out.println
。
運行 Groovy 示例
假設我將代碼保存在文件/home/amosli/developsoft/language/groovy/test/Hello.groovy 內,只要輸入以下代碼就能運行這個示例:
amosli@amosli-ThinkPad:~/developsoft/language/groovy/groovy-2.3.6/bin$ ./groovy ../../test/Hello.groovy Hello World!
如果已經配置了groovy的環境變量,那么只需要輸入以下命令即可:
root@amosli-ThinkPad:/home/amosli/developsoft/language/groovy/test# groovy Hello.groovy
Hello World!
在控制台上輸出 “Hello World!” 所需的工作就這么多。
更快捷的方式
amosli@amosli-ThinkPad:~/developsoft/language/groovy/groovy-2.3.6/bin$ ./groovy -e "println 'helloworld '" helloworld
如果已經配置了groovy的環境變量,那么只需要輸入以下命令即可:
root@amosli-ThinkPad:/home/amosli/developsoft/language/groovy/test# groovy -e "println 'helloworld '" helloworld
這會生成相同的結果,而且甚至無需定義任何文件!
3、Groovy 是沒有類型的 Java 代碼
很可能將 Groovy 當成是沒有規則的 Java 代碼。但實際上,Groovy 只是規則少一些。這一節的重點是使用 Groovy 編寫 Java 應用程序時可以不用考慮的一個 Java 編程的具體方面:類型定義。
為什么要有類型定義?
在 Java 中,如果要聲明一個 String
變量,則必須輸入:
String value = "Hello World";
但是,如果仔細想想,就會看出,等號右側的字符已經表明 value
的類型是 String
。所以,Groovy 允許省略 value
前面的 String
類型變量,並用 def
代替。
def value = "Hello World"
實際上,Groovy 會根據對象的值來判斷它的類型。
運行程序!
將 HelloWorld.groovy 文件中的代碼編輯成下面這樣:
String message = "Hello World" println message.class //class java.lang.String
4、通過 Groovy 進行循環
方式1:
這里可以定義i為int 或者 def ,或者不定義其類型
for(i = 0; i < 5; i++){ println i }
方式2:
使用in進行循環,其中..表示“到”,0..5表示0到5,類似於0<=5;這里循環6次;
for(i in 0..5){ println i }
可以使用0..<5進行限定,類似於0<5,循環5次;
5、Groovy中的集合
1)、Groovy 中的List
def range = 0..4 println range.class assert range instanceof List
請注意,assert
命令用來證明范圍是 java.util.List
的實例。接着運行這個代碼,證實該范圍現在是類型 List
的集合。
Groovy 的語法:
def coll = ["Groovy", "Java", "Ruby"] assert coll instanceof Collection assert coll instanceof ArrayList
你將會注意到,coll
對象看起來很像 Java 語言中的數組。實際上,它是一個Collection
。要在普通的 Java 代碼中得到集合的相同實例,必須執行以下操作:
Collection<String> coll = new ArrayList<String>(); coll.add("Groovy"); coll.add("Java"); coll.add("Ruby");
在 Java 代碼中,必須使用 add()
方法向 ArrayList
實例添加項。
而Groovy中則提供了3種方法:
coll.add("Python") coll << "Smalltalk" coll[5] = "Perl"
查找元素:
如果需要從集合中得到某個特定項,可以通過像上面那樣的位置參數獲取項。例如,如果想得到第二個項 “Java”,可以編寫下面這樣的代碼(請記住集合和數組都是從 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]
Groovy中的特殊方法:
def numbers = [1,2,3,4] assert numbers.join(",") == "1,2,3,4" assert [1,2,3,4,3].count(3) == 2
join() 和 count() 只是在任何項List上都可以調用的眾多方便方法中的兩個。分布操作符(spread operator) 是個特別方便的工具,使用這個工具不用在集合上迭代,就能夠調用集合的每個項上的方法。
假設有一個 String 列表,現在想將列表中的項目全部變成大寫,可以編寫以下代碼:
assert ["JAVA", "GROOVY"] ==
["Java", "Groovy"]*.toUpperCase()
請注意 *. 標記。對於以上列表中的每個值,都會調用 toUpperCase(),生成的集合中每個 String 實例都是大寫的。
2)Groovy中的Map
Java 語言中的映射是名稱-值對的集合。所以,要用 Java 代碼創建典型的映射,必須像下面這樣操作:
Map<String, String>map = new HashMap<String, String>(); map.put("name", "Andy"); map.put("VPN-#","45");
Groovy 使得處理映射的操作像處理列表一樣簡單 — 例如,可以用 Groovy 將上面的 Java 映射寫成
def hash = [name:"Andy", "VPN-#":45]
請注意,Groovy 映射中的鍵不必是 String
。在這個示例中,name
看起來像一個變量,但是在幕后,Groovy 會將它變成 String
。
驗證hash格式:
assert hash.getClass() == java.util.LinkedHashMap
Groovy 中Hash的Set/Get
//方法1 hash.put("id", 23) assert hash.get("name") == "Andy" //方法2 hash.dob = "01/29/76" //. 符號還可以用來獲取項。例如,使用以下方法可以獲取 dob 的值: assert hash.dob == "01/29/76" //方法3 assert hash["name"] == "Andy" hash["gender"] = "male" assert hash.gender == "male" assert hash["gender"] == "male"
請注意,在使用 []
語法從映射獲取項時,必須將項作為 String
引用。
6、Groovy 中的閉包
Java 的 Iterator
實例,用它在集合上迭代,就像下面這樣:
def acoll = ["Groovy", "Java", "Ruby"] for(Iterator iter = acoll.iterator(); iter.hasNext();){ println iter.next() }
請注意,each
直接在 acoll
實例內調用,而 acoll
實例的類型是 ArrayList
。在 each
調用之后,引入了一種新的語法 —{
,然后是一些代碼,然后是 }
。由 {}
包圍起來的代碼塊就是閉包。
def acoll = ["Groovy", "Java", "Ruby"]
acoll.each{
println it
}
閉包中的 it
變量是一個關鍵字,指向被調用的外部集合的每個值 — 它是默認值,可以用傳遞給閉包的參數覆蓋它。下面的代碼執行同樣的操作,但使用自己的項變量:
def acoll = ["Groovy", "Java", "Ruby"] acoll.each{ value -> println value }
在這個示例中,用 value 代替了 Groovy 的默認 it。
def hash = [name:"Andy", "VPN-#":45] hash.each{ key, value -> println "${key} : ${value}" }
請注意,閉包還允許使用多個參數 — 在這個示例中,上面的代碼包含兩個參數(key
和 value
)。
請記住,凡是集合或一系列的內容,都可以使用下面這樣的代碼進行迭代。
> "amosli".each{
println it.toUpperCase();
}
A
M
O
S
L
I
def excite = { word-> return "this is ${word} " };
這段代碼是名為 excite 的閉包。這個閉包接受一個參數(名為 word),返回的 String 是 word 變量加兩個感嘆號。請注意在 String 實例中替換 的用法。在 String 中使用 ${value}語法將告訴 Groovy 替換 String 中的某個變量的值。可以將這個語法當成 return word + "!!" 的快捷方式。
//可以通過兩種方法調用閉包:直接調用或者通過 call() 方法調用。 excite("Java"); excite.call("Groovy")
輸出:this is Groovy
7、Groovy 中的類
新建一個類song:
class Song { def name def artist def genre }
class SongExample { static void main(args) { def sng = new Song(name:"Le Freak", artist:"Chic", genre:"Disco") } }
Groovy 自動提供一個構造函數,構造函數接受一個名稱-值對的映射,這些名稱-值對與類的屬性相對應。這是 Groovy 的一項開箱即用的功能 — 用於類中定義的任何屬性,Groovy 允許將存儲了大量值的映射傳給構造函數。映射的這種用法很有意義,例如,您不用初始化對象的每個屬性。
也可以添加下面這樣的代碼:
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."
在 Song
類中,添加以下代碼:
String toString(){ "${name}, ${artist}, ${genre}" }
8、Groovy中的單元測試
@Test public void test(){ def sng2 = new Song(name:"Kung Fu Fighting", genre:"Disco") println sng2.getArtist(); }
在Intellij 中只需要加入@Test注解就可以使用JUnit 測試
加個?可以防止空指針的錯誤:
def getArtist(){ artist?.toUpperCase(); }
9、擴展
如果需要用Groovy做web 項目的話可以去了解一下Grails框架。
本文源碼:https://github.com/amosli/groovy
參考:
1.http://confluence.jetbrains.com/display/IntelliJIDEA/Groovy
2.http://www.ibm.com/developerworks/cn/education/java/j-groovy/j-groovy.html
3.http://groovy.codehaus.org/
4.http://confluence.jetbrains.com/display/IntelliJIDEA/Getting+Started+with+Grails