00、故事的起源
“二哥,聽說上一篇《多線程》被 CSDN 創始人蔣濤點贊了?”三妹對她提議的《教妹學 Java》專欄一直很關心。
“嗯,有點激動。剛開始還以為是個馬甲,沒想到是真人!”
“其實蔣濤點贊的文章很多很多了,二哥的只是其中一篇而已。”三妹出乎意料地潑起了冷水。
“你說得沒錯。但這的確給我注入了新的能量,蔣濤畢竟是業界的大佬啊。”
“那就讓我們開始新的篇章吧!我繼續來提問,二哥你繼續回答。”三妹已經迫不及待了。
01、二哥,什么是 Groovy 啊?
三妹啊,聽哥來給你慢慢講啊。
Groovy 是一種面向對象的動態類型語言,跟 Java 一樣,可以運行在 JVM 上。
之所以稱 Groovy 為“動態”類型語言,是因為 Groovy 的語法源於 Smalltalk 和 Ruby,提供了比 Java 更簡單、更靈活的語法,可以在運行時動態地進行類型檢查。
Java 語言是一種固定類型語言,比如說整形變量 int a = 0;,字符串變量 String s = "Wanger"。但在 Groovy 中,不必指定變量的類型(可選的),變量的類型是在聲明(或返回)的時候確定的。
比如說可以把一個整形賦值給變量 a,然后緊接着把一個字符串賦值給變量 a。
a 雖然沒有指定類型,但 a 在被賦值為 0 的時候為整形,被賦值為 “Wanger” 的時候為字符串類型。
Groovy 代碼能夠完美地兼容 Java 代碼,可以用來作為 Java 的一種補充。你甚至可以用 Groovy 在 Java 平台上進行 Java 編程,使用方式基本上和使用 Java 代碼的方式相同。
許多 Java 開發人員非常喜歡 Groovy 代碼和 Java 代碼的相似性。因為從學習的角度看,如果知道如何編寫 Java 代碼,那么也就知道如何編寫 Groovy 代碼。
Groovy 之所以能夠獲得 Java 開發者的青睞,最主要原因在於完成同樣的任務所需的 Groovy 代碼比 Java 代碼更少,因為 Groovy 具有松散的語法(允許省略分號)和一些特殊功能(比如說 JavaScript 中經常提到的閉包)。
02、二哥,能否 Hello World 一下?
三妹,Hello World 是必須的。就像你去買包包,總要先試試,再貨比三家,對吧?
還記得用 Java 編寫的 Hello World 嗎?
然后我們編譯它:
再然后我們運行已經編譯好的類:
不出意外的話,你會在屏幕上看到“Hello World”。
那如果用 Groovy 來編寫 Hello World 呢?
嗨,有沒有被驚訝到了呢?
1)Groovy 松散的語法讓我們不需要為打印 “Hello World” 這樣的簡單操作定義類。
2)Groovy 會非常聰明地為我們在 println 前面加上 System.out。
3)main 方法也不需要了。
假設代碼保存在 Wanger.groovy 文件中,可以跳過編譯階段直接運行:
為什么連編譯也不需要呢?因為 Groovy 屬於腳本語言,可以在運行時進行解釋。當然了,你也可以按照編譯再運行的步驟來:
用 groovyc 編譯的 Groovy 代碼會產生標准的 Java 字節碼,然后也可以通過 java 命令運行生成的字節碼。
注意,在命令行中運行 Groovy 代碼的前提是,你需要先到 Groovy 的官網下載免安裝包,再將其解壓后配置到環境變量中,就像當初你配置 Java 環境變量那樣。
下載地址如下:
https://groovy.apache.org/download.html
03、二哥,怎么安裝 Groovy 啊?
三妹啊,由於哥一直使用 Eclipse 作為集成開發環境,所以這次的安裝就以 Eclipse 的 Groovy 插件為例。
第一步,打開 Eclipse,在 Help 菜單中選擇 Eclipse Marketplace,搜索 groovy 關鍵字,結果如下圖所示。
第二步,點擊 install 按鈕,在功能選擇對話框中勾選全部,然后點擊 Confirm 按鈕。
第三步,在許可證確認對話框中勾選 I accept the terms of the license agreement,點擊 Finish 按鈕。
第四步,安裝成功后,重啟 Eclipse。這時候,就可以創建一個 Groovy 的項目了,如下圖所示。
第五步,創建一個 Groovy 的測試類,勾選 static void main(args) 選項,如下圖所示。
生成的代碼如下:
這和之前 Java 版的 HelloWorld 驚人地相似,但沒有 public 修飾符,並且 main 方法的參數沒有類型。
這時候,我們在 main 方法內加入 println "Hello World":
我們可以直接選擇 Run As Java Application 來運行 Groovy 代碼,因為 Groovy 實際上就是 Java,只不過語法有所不同,多數情況下會短一些,但 Groovy 代碼 100% 符合 Java 字節碼的標准。
04、二哥,Groovy 有哪些 Java 不具備的特性呢?
三妹啊,你這個問題就問得很到位啊。
大多數情況下,Java 開發者更希望利用 Groovy 的特性來替代一些 Java 中不夠優雅的解決方案。
像 Groovy 中一些可以省略的語法,比如說:
- 語句結束處的分號;
- 返回語句的 return 關鍵字;
- 方法參數兩邊的括號;
- public 訪問限定符;
- ……
這些並不是 Java 開發者要學習 Groovy 這門新語言的動力,那是什么呢?
1)Groovy List
在 Java 中,List 的操作方法大致如下:
但在 Groovy 中,操作方法變得更加便捷了。
可以像定義數組一樣定義 list,就像下面這樣:
向 list 中添加元素也變得多種多樣:
也可以像數組一樣取出元素:
2)Groovy Map
在 Java 中,Map 的操作方法大致如下:
但在 Groovy 中,操作方法變得更加便捷了。
可以按照以下方法定義一個 Map:
注意:Groovy 中的鍵不必是字符串(可以不帶雙引號)。
向 map 中添加元素也變得多種多樣:
取出元素可以使用 . 或者 []:
3)Groovy 閉包
JavaScript 開發者一定不會對下面這句話感到陌生:
當一個函數被創建並傳遞或從另一個函數返回時,它會攜帶一個背包,背包中是函數聲明時作用域內的所有變量。
這句話里面的“背包”就對閉包的一個恰當的比喻。Groovy 的官網是這樣描述閉包的:
A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable.
大致的意思就是說,Groovy 閉包是一個開放的、匿名的代碼塊,可以接受參數,並把返回值賦值給變量。
閉包的定義方式如下:
其中 [closureParameters] 是以逗號分隔的參數列表,statements 是 0 個或者多個 Groovy 語句。 -> 操作符用於將參數列表與 Groovy 語句隔開。
我們來用閉包遍歷一下列表,方式如下:
其中 { x -> println x} 就是一個閉包,把它作為 each() 方法的參數就可以將 list 中的元素取出,並且打印出來。
另外,閉包還有一個默認參數 it,它不需要像 x 一樣聲明出來,於是遍歷 list 的代碼就變成了下面這樣:
接下來,我們再來看一下遍歷 map 的方法,就是像變魔法一樣。
可以使用默認的 it 作為元素,it.key 為鍵,it.value 為值。
注意: each() 方法的 () 還可以省略。
還可以自定義變量 item 作為元素,item.key 為鍵,item.value 為值。
或者,直接使用 key 和 value。
我們來自定義一個閉包,就像下面這樣:
addX 是這個閉包的名字,它接受一個參數 x,返回 x + 1。然后,我們可以這樣來調用閉包:
閉包在 Groovy 中不僅是一個方法,也是一個對象,所以它既可以作為參數傳遞,也可以調用方法。
05、故事的未完待續
“二哥,Groovy 有這么多引人注目的特性,使得它成為了一門出色的可以和 Java 共用的語言。但用 Groovy 的人並不多呢?”三妹所有所思的問。
“三妹啊,這是一個好問題呢,不過答案也顯而易見。下圖來自於 Groovy 官網,可以看到很多大廠的名字:Google、IBM、Linkedin、SONY。”
“不過,我聽說 Java 8 中出現的 Lambda 表達式也能寫出和 Groovy 一樣簡潔靈活的代碼,你能不能教教我呢?”三妹的眼睛里充滿了期待。
“三妹,你竟然知道 Lambda表達式……”







