Gradle 之語言基礎 Groovy
最近在學習 Android 中 Gradle 相關的知識,如果想學好 Gradle,必要的 Groovy 基礎是不可少的。Groovy 語言的知識也是非常多的,如果只是想在 Android Gradle 這個範圍內使用 Groovy,會 Groovy 的基礎即可,ofollow,noindex">Groovy 語言文件 。
一. Android Gradle 概述
Groovy 是從 Java 衍生出來的,Groovy 的原始碼檔案.groovy
也是編譯成為 .class 檔案,然後執行在 JVM 虛擬機器上的。其目標是,不管是作為指令碼語言,還是程式語言,都可以簡單、直接的使用。在 Android 的 Gradle 中,Groovy 更多的是用於編寫指令碼。如果會 Java,學習 Groovy 會比較簡單,甚至可以混寫 Java 和 Groovy 語法。
Groovy 相比 Java 語言來講,更加的方便靈活,更多的語法糖使編寫 Groovy 程式碼更加的簡潔,而且在 Groovy 中具有函數語言程式設計的思想。比如:Groovy 中非常重要的閉包Closure
概念(類似於 C 語言中的函式指標),可以當做一個函式也執行,也可以當做某個函式的引數傳入到函式中去,也可以當做一個函式的返回值返回。
想學好 Gradle,除了必要的 Groovy 知識基礎以外,還需要了解其他兩個基礎知識:Android DSL 和 Gradle DSL。
DSL 是 Domain Specific Language(領域特定語言)的縮寫,其定義是:針對某一領域,具有受限表達性的一種計算機程式設計語言。學習 Android Gradle,Android DSL 和 Gradle DSL 也是需要學習的,好在有官方的文件Android DSL 文件 和Gradle DSL 文件 ,學習起來就比較方便。在這篇文章中,不會過多地介紹 Android DSL 和 Gradle DSL,在下篇文章中會介紹。
好了,廢話不多說,接下來就來學習 Groovy 的語法基礎吧。為了學習的時候,可以執行 gradle 指令碼,請先在電腦上配置好 gradle 的環境變數,這樣就可以方便地執行 gradle 指令碼了。
二. Groovy 語言基礎
由於篇幅所限,本篇文章也只能作為一個引子,介紹基礎的 Groovy 語言概念,詳細的還需要從Groovy 語言文件 學習。而且我個人認為,如果遇到什麼不懂的、不會的,從官方文件上學習是最好的學習途徑;或者至少先從官方文件上學習,再去學習其他的資料,將自己學習的和資料的進行對比思考,這樣會更有助於個人的成長
為了避免無意義的內容,只介紹和 Java 有區別的地方,相同的地方不作說明。
2.1 變數
- Groovy 中宣告的變數,預設的修飾符是 public 的
-
Groovy 中宣告變數時,如果一行只宣告一個變數則可以省略末尾的
;
,但是如果一行聲明瞭多個變數,變數與變數之間則不可以省略;
-
在 Groovy 中宣告變數,也可以使用關鍵字
def
,def
只是聲明瞭一個變數,變數的實際型別根據該變數的物件決定。def
和 JavaScript 中的val
有點像,從def
可以看出 Groovy 也是一門動態語言 -
Groovy 中字串
String
,可以使用單引號 'String',也可以使用雙引號 "String" -
在 Groovy 中的 String,可以通過
${}
做佔位符表示式向字串中插入值,在{}
中寫表示式或變數都可以,使用${}
的字串必須使用雙引號 ""
int version = 1 Boolean isDebug = true def language = 'groovy' def message = "Hello from ${language + 1}, the result is ${isDebug}." task hello { doLast{ println message } }
上面程式碼的執行輸出是:
> Task :hello Hello from groovy1, the result is true.
2.2 List
- 因為在 Groovy 中沒有定義任何集合類,所以 Groovy 中的 List 使用的是 JDK 中的 java.util.List
- 在 Groovy 中的一個 List 中可以新增多種型別的物件元素
-
建立 List 物件使用
[]
,而不是 Java 中的{}
,防止和 Groovy 中的閉包 Closure {}
混淆 -
可以通過
[index]
的方式修改和訪問 List 中的元素 -
可以通過
<<
向 List 中新增元素,<<
實際是leftShift()
方法 -
可以通過負數,從後向前訪問 List 中的元素,比如
[-1]
表示最後一個元素 -
可以通過
[index1, index2]
同時訪問 List 中的多個元素,返回結果仍是一個List -
可以通過
[index1..index2]
一次性訪問 List 中某個範圍內的陣列,返回結果也是一個 List
ArrayList arrayList = ['arrayOne', 'arrayTwo', 'arrayThree'] LinkedList linkedList = ['linkedOne', 'linkedTwo', 'linkedThree'] List list = [1, 2, true] def listDef = ['one', 2, true, 4, '5'] task helloList { doLast { println listDef println arrayList println linkedList println list println list[0] println list[-1] list << 4 println list[-1] println list[1, 3] println list[1..3] } }
輸出如下所示:
> Task :app:helloList [one, 2, true, 4, 5] [arrayOne, arrayTwo, arrayThree] [linkedOne, linkedTwo, linkedThree] [1, 2, true] 1 true 4 [2, 4] [2, true, 4]
2.3 Arrays
Groovy 中的陣列和 Java 中的陣列區別並不大,也不過多的做介紹
-
Groovy 中的陣列使用
[]
初始化,並不使用{}
,防止和 Groovy 中的閉包 Closure {}
混淆 -
陣列不支援
<<
向 Arrays 中新增元素
String[] arrayStrings = ["one", "two", 'three']; def arrayInts = [1, 2, 3] as int[] task hello { doLast { println arrayStrings[0] println arrayStrings[1] println arrayStrings[-1] // arrayStrings << 'four'// Arrays 不支援 << println arrayStrings println arrayInts } }
輸出如下所示:
> Task :hello one two three [one, two, three] [1, 2, 3]
2.4 Map
-
Groovy 中的 Map 是以
:
作為 key 和 value 的連線,並且以,
做為每一項的分隔符的 - Map 中的 key 既可以是字串也可以是阿拉伯數字
-
可以通過
[key]
和.key
的形式訪問或向 map 中賦值,訪問的時候如果不存在該key
,則會返回null
-
如果以變數作為 key 訪問 map 時,記得需要加上
()
def maps = [red: '#FF0000', green: '#00FF00', blue: '#0000FF'] def mapNums = [1: 'one', 2: 'two', 3: 'three', 100: 'four'] def key = 'name' def mapKey = [key: 'value'] def mapKey1 = [(key): 'value1'] task helloMaps { doLast { println maps['red'] println maps.green maps['pink'] = '#FF00FF' maps.yello = '#FFFF00' println maps['pink'] println maps.yello println maps.white println mapNums[1] println mapNums[100] println mapNums[5] println mapKey['key'] println mapKey['name'] println mapKey1['name'] } }
上述程式碼的輸出是
> Task :app:helloMaps #FF0000 #00FF00 #FF00FF #FFFF00 null one four null value null value1
2.5 Class 和物件
Groovy 中的 Class 和 Java 中的 Class 區別並不大,主要有以下幾個區別
-
如果類、方法沒有修飾符的話,預設是
public
修飾符的 -
如果類中的變數
fields
沒有被修飾符修飾的話,會自動成為一個properties
,properties
是公有的,並且會自動生成該properties
的 setter 和 getter 方法 -
在 Java 中,檔名和主類的名稱必須一致,但是 Groovy 中並沒有這個限制,且在一個 Groovy 檔案中可以出現多個
public
的類 - 在一個 Groovy 檔案中可以在類之外定義方法或語句,這種檔案就是指令碼了
class Student { def name def age private String work public String lover def Student(String name) { this.name = name } } task helloClass { doLast { def student = new Student('lijiankun24') println student.name println student.getAge() println student.lover // println student.getLover()// Student 中並沒有 getLover() 這個方法 // println student.getWork()// Student 中並沒有 getWork() 這個方法 } }
輸出結果如下:
> Task :app:helloClass lijiankun24 null null
2.6 函式
Groovy 中的函式和 Java 中的函式並沒有太大的區別
-
函式一定會有返回值,如果沒有顯示的使用
return
返回值的話,函式的最後一行語句的執行結果作為值返回,可能返回值是個null
- 如果函式有引數,呼叫函式的時候,可以省略函式的括號,函式名和引數之間需要用空格間隔;如果函式沒有引數,呼叫函式的時候就不能省略括號
- 函式內不可以訪問函式外的變數
def message = 'message' def printMessage () { println message } void printName(String name) { println name } void printPerson(String name, age) { println "The name is ${name} and the age is ${age}" } task helloFunction { doLast { println printName('xiaoming') printPerson'xiaoming', 20 // println printMessage() 會執行異常 } }
輸出結果如下所示:
> Task :app:helloFunction xiaoming null The name is xiaoming and the age is 20
2.7 閉包Closure
閉包closure
是 Java 中沒有的,也是需要重點學習的,學好closure
對理解 Android 中的 Gradle 會有莫大的幫助
-
閉包
closure
的定義如下,其中[closureParameters ->]
作為引數部分,是可以省略的
{ [closureParameters -> ] statements }
-
closure
其實是 Groovy 中groovy.lang.Closure
的一個類 -
閉包
closure
可以訪問閉包之外的變數 -
閉包
closure
可以有三種呼叫方式,如下程式碼所示 -
閉包
closure
的引數可以省略,預設是有個it
引數的 -
閉包
closure
也可以作為另一個閉包closure
的引數
// 閉包可以訪問閉包之外的變數 def message = 'closure is good' def printMessage = { println "The message is '${message}'" } // 閉包實際上是一個 `groovy.lang.Closure` 類 Closure<Boolean> booleanClosure = { return it == 'xiaoming' } // 閉包可以省略引數,預設有一個 `it` 的引數 def testClosure = { println "I am a closure, the params is ${it}." } // 閉包可以有多個引數,引數可以指定型別,也可以不指定型別 def testClosureParams = { name, int age -> println "I am a closure, the params is ${name}." } // 閉包可以作為另一個閉包的引數 def paramsClosure = { name, closure -> if (closure(name)) { println 'The input name is xiaoming' } else { println 'The input name is not xiaoming' } } task helloClosure { doLast { printMessage() println booleanClosure('xiaoming') println booleanClosure('test') // 閉包的三種呼叫方式 testClosure 'xiaoming' testClosure.call('xiaoming') testClosure('xiaoming') testClosureParams('xiaoming', 20) // 閉包 booleanClosure 作為閉包 paramsClosure 的引數 paramsClosure('xiaoming', booleanClosure) paramsClosure('test', booleanClosure) // 可以在呼叫閉包的時候才去定義引數閉包的定義,使用非常方便簡潔 paramsClosure('xiaoming', { name -> name.toUpperCase() == 'XIAOMING' }) } }
輸出如下所示
> Task :app:helloClosure The message is 'closure is good' true false I am a closure, the params is xiaoming. I am a closure, the params is xiaoming. I am a closure, the params is xiaoming. I am a closure, the params is xiaoming. The input name is xiaoming The input name is not xiaoming The input name is xiaoming
Groovy 的基礎知識就是這麼多,如果想學習更多的內容,建議學習Groovy 文件