Groovy 教程系列(一)-- Groovy 入門
概述
Groovy 是一種基於Java平臺的面嚮物件語言。Groovy 的語法和 Java 非常的相似,可以使用現有的 Java 庫來進行 Groovy 開發。可以將它想像成 Java 語言的一種更加簡單、表達能力更強的變體。 用 Groovy 編寫的任何內容都可以編譯成標準的 Java 類檔案並在 Java 程式碼中重用。類似地,用標準 Java 程式碼編寫的內容也可以在 Groovy 中重用。所以,可以輕易地使用 Groovy 為 Java 程式碼編寫單元測試。而且,如果用 Groovy 編寫一個方便的小工具,那麼也可以在 Java 程式中使用這個小工具。 我們為什麼要學習 Groovy 語言呢? Groovy 是一種更有生產力的語言。它具有鬆散的語法和一些特殊功能,能夠加快編碼速度。 在 Android 開發中,我們會經常接觸 Gradle,而前面部落格中我們說過,Gradle 是一個使用 Groovy 語言實現的用於構建專案的框架,如果不懂 Groovy,你就不能說精通了 Gradle。 前面介紹的幾篇關於 Gradle 的部落格中都有涉及到 Groovy,比如 Gradle 的配置和外掛開發,那麼現在再讀 Grovvy 的介紹的文章,會有一種豁然開朗的感覺。 Groovy 語言的一些特點:
- Groovy 的鬆散的 Java 語法允許省略分號和 return 關鍵字。
- 變數的型別和方法的返回值也是可以省略的。
- 方法呼叫時,括號也是可以省略的。
- 除非另行指定,Groovy 的所有內容都為 public。
- Groovy 允許定義簡單指令碼,同時無需定義正規的 class 物件。
- Groovy 在普通的常用 Java 物件上增加了一些獨特的方法和快捷方式,使得它們更容易使用。
- Groovy 語法還允許省略變數型別。
官方網站Groovy API 文件:遇到不懂的類或者方法,這個是好幫手。
執行環境
我們可以安裝 Groovy SDK 來設定執行環境,如果你不想麻煩,也可以在Android工程中執行 Groovy。
在 build.gradle 中編寫程式碼
這一點在前面的部落格 Gradle 使用指南 – Gradle Task 其實已經有所運用,即在裡面建立一個 Task,然後在 Task 中編寫 Groovy 程式碼即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
task hello { doFirst { println 'task hello doFirst' Student st = new Student() st.setStudentName("Joe") println(st.getStudentName()); } } class Student { String StudentName; } |
然後執行 ./gradlew hello
命令即可。
以外掛的方式
在 build.gradle 中直接呼叫 Groovy 方法
這一種方式是前面兩種方式的結合,但是不用建立 gradle 外掛。 在 buildSrc 中建立 TestGroovy.groovy 檔案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.android.hq.myfirstplugin public class TestGroovy { public static void testGroovy() { Student st = new Student() st.setStudentName("James"); println(st.getStudentName()) } public static class Student { String StudentName; } } |
在 Task 中呼叫方法:
1 2 3 4 5 6 |
task hello { doFirst { println 'task hello doFirst' TestGroovy.testGroovy() } } |
然後執行 ./gradlew hello
命令即可;
Groovy 入門
由於 Groovy 和 Java 極其的類似,因此,基本的語法規範就參考W3C school Groovy教程即可,下面只來介紹一下 Groovy 的一些新特性。
變數型別定義和方法宣告
在 Java 中,變數是必須指定型別的,但是在 Groovy 中,所有的變數型別都可以用 def
去指定,Groovy 會根據物件的值來判斷它的型別。
1 2 3 4 |
def helloStr = "Hello World"; def a = 1, b = 2 println helloStr println a + b |
函式的的返回值的型別當然也可以用 def
來宣告:
1 2 3 |
def getStr() { return "Hello World" } |
在宣告函式時,引數變數的型別是可以省略的:
1 2 3 |
def add(arg1, arg2) { return arg1+arg2 } |
前面我們說過,方法返回值的關鍵字 return
是可以省略的:
1 2 3 |
def add(arg1, arg2) { arg1+arg2 } |
方法呼叫時括號是可以省略的,見 println a + b
的呼叫。
在 Groovy 中,型別是弱化的,所有的型別都可以動態推斷,但是 Groovy 仍然是強型別的語言,型別不匹配仍然會報錯;
上述兩個類完全一致,只有有屬性就有Getter/Setter;同理,只要有Getter/Setter,那麼它就有隱含屬性。
字串
在Groovy中有兩種風格的字串:String(java.lang.String)和GString(groovy.lang.GString)。GString允許有佔位符而且允許在執行時對佔位符進行解析和計算。 這裡我們只介紹對佔位符的一種使用:嵌入表示式
嵌入表示式
1 2 3 4 |
def worldStr = "World" def helloStr = "Hello ${worldStr}"; println helloStr println "value: ${3+3}" |
除了${}佔位符的{}其實是可以省去的。 佔位符裡面可以包含一個閉包表示式。
物件
Getter/Setter 方法
在Groovy中,物件的 Getter/Setter 方法和屬性是預設關聯的,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public static class Student { String StudentName; } public static class Student { String StudentName; String getStudentName() { return StudentName } void setStudentName(String studentName) { StudentName = studentName } } |
with 方法
當對同一個物件進行操作時,可以使用 with
:
1 2 3 4 5 6 7 8 9 10 11 12 |
Student st = new Student() st.with { id = 10; name = "James"; } println st.getName() ...... public static class Student { def name def id } |
join 方法
用指定的字元連線集合中的元素:
1 2 |
def list = [2017,1,6] println list.join("-") |
其他實用方法請參考 Groovy API 文件中的 DefaultGroovyMethods
。
閉包
閉包是一個短的匿名程式碼塊。它通常跨越幾行程式碼。一個方法甚至可以將程式碼塊作為引數。它們是匿名的。 下面是一個簡單閉包的例子:
1 2 3 4 5 6 7 8 9 |
def clos = { def worldStr = "World" def helloStr = "Hello $worldStr"; println helloStr def person = [name: 'Joe', age: 36] println "$person.name is $person.age years old" } clos.call() |
程式碼行 {…}被稱為閉包。此識別符號引用的程式碼塊可以使用call語句執行。
閉包也可以包含形式引數,以使它們更有用,就像Groovy中的方法一樣。
1 2 3 4 5 |
def clos = { param -> def helloStr = "Hello $param"; println helloStr } clos.call("World") |
如果閉包不指定引數,那麼它會有一個隱含的引數 it
:
1 2 3 4 5 |
def clos = { def helloStr = "Hello $it"; println helloStr } clos.call("World") |
閉包可以有返回值:
1 2 3 4 5 |
def clos = { def helloStr = "Hello $it"; return helloStr } println clos.call("World") |
閉包還可以作方法的引數。