概述
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") |
閉包還可以作方法的參數。