教妹學 Java:動態伴侶 Groovy

00、故事的起源

「二哥,據說上一篇《多線程》被 CSDN 創始人蔣濤點讚了?」三妹對她提議的《教妹學 Java》專欄一直很關心。html

「嗯,有點激動。剛開始還覺得是個馬甲,沒想到是真人!」java

「其實蔣濤點讚的文章不少不少了,二哥的只是其中一篇而已。」三妹出乎意料地潑起了冷水。apache

「你說得沒錯。但這的確給我注入了新的能量,蔣濤畢竟是業界的大佬啊。」編程

「那就讓咱們開始新的篇章吧!我繼續來提問,二哥你繼續回答。」三妹已經火燒眉毛了。數組

0一、二哥,什麼是 Groovy 啊?

三妹啊,聽哥來給你慢慢講啊。bash

Groovy 是一種面向對象的動態類型語言,跟 Java 同樣,能夠運行在 JVM 上。多線程

之因此稱 Groovy 爲「動態」類型語言,是由於 Groovy 的語法源於 Smalltalk 和 Ruby,提供了比 Java 更簡單、更靈活的語法,能夠在運行時動態地進行類型檢查。閉包

Java 語言是一種固定類型語言,好比說整形變量 int a = 0;,字符串變量 String s = "Wanger"。但在 Groovy 中,沒必要指定變量的類型(可選的),變量的類型是在聲明(或返回)的時候肯定的。函數

好比說能夠把一個整形賦值給變量 a,而後緊接着把一個字符串賦值給變量 a。學習

a = 0;
a = "Wanger";
複製代碼

a 雖然沒有指定類型,但 a 在被賦值爲 0 的時候爲整形,被賦值爲 「Wanger」 的時候爲字符串類型。

Groovy 代碼可以完美地兼容 Java 代碼,能夠用來做爲 Java 的一種補充。你甚至能夠用 Groovy 在 Java 平臺上進行 Java 編程,使用方式基本上和使用 Java 代碼的方式相同。

許多 Java 開發人員很是喜歡 Groovy 代碼和 Java 代碼的類似性。由於從學習的角度看,若是知道如何編寫 Java 代碼,那麼也就知道如何編寫 Groovy 代碼。

Groovy 之因此可以得到 Java 開發者的青睞,最主要緣由在於完成一樣的任務所需的 Groovy 代碼比 Java 代碼更少,由於 Groovy 具備鬆散的語法(容許省略分號)和一些特殊功能(好比說 JavaScript 中常常提到的閉包)。

0二、二哥,可否 Hello World 一下?

三妹,Hello World 是必須的。就像你去買包包,總要先試試,再貨比三家,對吧?

還記得用 Java 編寫的 Hello World 嗎?

public class Wanger {
    public static void main(String [] args) {
        System.out.println("Hello World");
    }
}
複製代碼

而後咱們編譯它:

javac Wanger.java
複製代碼

再而後咱們運行已經編譯好的類:

java Wanger
複製代碼

不出意外的話,你會在屏幕上看到「Hello World」。

那若是用 Groovy 來編寫 Hello World 呢?

println "Hello World"
複製代碼

嗨,有沒有被驚訝到了呢?

1)Groovy 鬆散的語法讓咱們不須要爲打印 「Hello World」 這樣的簡單操做定義類。

2)Groovy 會很是聰明地爲咱們在 println 前面加上 System.out。

3)main 方法也不須要了。

假設代碼保存在 Wanger.groovy 文件中,能夠跳過編譯階段直接運行:

groovy Wanger.groovy
複製代碼

爲何連編譯也不須要呢?由於 Groovy 屬於腳本語言,能夠在運行時進行解釋。固然了,你也能夠按照編譯再運行的步驟來:

groovyc Wanger.groovy
groovy Wanger
複製代碼

用 groovyc 編譯的 Groovy 代碼會產生標準的 Java 字節碼,而後也能夠經過 java 命令運行生成的字節碼。

注意,在命令行中運行 Groovy 代碼的前提是,你須要先到 Groovy 的官網下載免安裝包,再將其解壓後配置到環境變量中,就像當初你配置 Java 環境變量那樣。

下載地址以下:

groovy.apache.org/download.ht…

0三、二哥,怎麼安裝 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) 選項,以下圖所示。

生成的代碼以下:

package groovyTest

class Wanger {

    static void main(args) {
        
    }
}
複製代碼

這和以前 Java 版的 HelloWorld 驚人地類似,但沒有 public 修飾符,而且 main 方法的參數沒有類型。

這時候,咱們在 main 方法內加入 println "Hello World"

package groovyTest

class Wanger {

    static void main(args) {
        println "Hello World"
    }
}
複製代碼

咱們能夠直接選擇 Run As Java Application 來運行 Groovy 代碼,由於 Groovy 實際上就是 Java,只不過語法有所不一樣,多數狀況下會短一些,但 Groovy 代碼 100% 符合 Java 字節碼的標準。

0四、二哥,Groovy 有哪些 Java 不具有的特性呢?

三妹啊,你這個問題就問得很到位啊。

大多數狀況下,Java 開發者更但願利用 Groovy 的特性來替代一些 Java 中不夠優雅的解決方案。

像 Groovy 中一些能夠省略的語法,好比說:

  • 語句結束處的分號;
  • 返回語句的 return 關鍵字;
  • 方法參數兩邊的括號;
  • public 訪問限定符;
  • ......

這些並非 Java 開發者要學習 Groovy 這門新語言的動力,那是什麼呢?

1)Groovy List

在 Java 中,List 的操做方法大體以下:

List<String> list = new ArrayList<>();
list.add("沉默");
list.add("王二");

for (String s : list) {
    System.out.println(s);
}
複製代碼

但在 Groovy 中,操做方法變得更加便捷了。

能夠像定義數組同樣定義 list,就像下面這樣:

def list = ["沉默", "王二"];
複製代碼

向 list 中添加元素也變得多種多樣:

list.add("勇士");
list << "猛龍";
list[4] = "火箭";
複製代碼

也能夠像數組同樣取出元素:

def wanger = list[1];
複製代碼

2)Groovy Map

在 Java 中,Map 的操做方法大體以下:

Map<String, String> map = new HashMap<>();
map.put("name", "沉默王二");
複製代碼

但在 Groovy 中,操做方法變得更加便捷了。

能夠按照如下方法定義一個 Map:

def map = [name:"沉默王二", "age":18];
複製代碼

注意:Groovy 中的鍵沒必要是字符串(能夠不帶雙引號)。

向 map 中添加元素也變得多種多樣:

map.put("money", 10000000);
map.sex = "保密";
map["work"] = "自由職業";
複製代碼

取出元素可使用 . 或者 []

map.money;
map["work"]
複製代碼

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 }
複製代碼

其中 [closureParameters] 是以逗號分隔的參數列表,statements 是 0 個或者多個 Groovy 語句。 -> 操做符用於將參數列表與 Groovy 語句隔開。

咱們來用閉包遍歷一下列表,方式以下:

list.each({ x -> println x});
複製代碼

其中 { x -> println x} 就是一個閉包,把它做爲 each() 方法的參數就能夠將 list 中的元素取出,而且打印出來。

另外,閉包還有一個默認參數 it,它不須要像 x 同樣聲明出來,因而遍歷 list 的代碼就變成了下面這樣:

list.each({println it});
複製代碼

接下來,咱們再來看一下遍歷 map 的方法,就是像變魔法同樣。

可使用默認的 it 做爲元素,it.key 爲鍵,it.value 爲值。

map.each { println it.key + it.value }
複製代碼

注意: each() 方法的 () 還能夠省略。

還能夠自定義變量 item 做爲元素,item.key 爲鍵,item.value 爲值。

map.each { entry -> println entry.key + entry.value }
複製代碼

或者,直接使用 key 和 value。

map.each { key, val -> println  key + val }
複製代碼

咱們來自定義一個閉包,就像下面這樣:

def addX = { x ->
	return x + 1;
};
複製代碼

addX 是這個閉包的名字,它接受一個參數 x,返回 x + 1。而後,咱們能夠這樣來調用閉包:

println addX(3);
println addX.call(addX(3));
複製代碼

閉包在 Groovy 中不只是一個方法,也是一個對象,因此它既能夠做爲參數傳遞,也能夠調用方法。

0五、故事的未完待續

「二哥,Groovy 有這麼多引人注目的特性,使得它成爲了一門出色的能夠和 Java 共用的語言。但用 Groovy 的人並很少呢?」三妹全部所思的問。

「三妹啊,這是一個好問題呢,不過答案也顯而易見。下圖來自於 Groovy 官網,能夠看到不少大廠的名字:Google、IBM、Linkedin、SONY。」

「不過,我據說 Java 8 中出現的 Lambda 表達式也能寫出和 Groovy 同樣簡潔靈活的代碼,你能不能教教我呢?」三妹的眼睛裏充滿了期待。

「三妹,你居然知道 Lambda表達式......」

相關文章
相關標籤/搜索