上一篇 學習了 Gradle 的入門知識,Gradle 基於 Groovy,今天學習一下 Groovy 的基礎知識,Groovy 是基於 JVM 虛擬機的一種動態語言,語法與 Java 語法類似,Groovy 完全兼容 Java,每個 Gradle 文件都是一個 Groovy 腳本文件,Gradle 文件基於 Groovy 語法,而 Groovy 又兼容 Java,故可以在 Gradle 文件中寫 Java 代碼,在此基礎上增加了很多新特性,如支持閉包、DSL 等,可以說 Groovy 是一門非常靈活的動態腳本語言,針對 Gradle 來學習一下 Groovy 的一些基礎知識。
- 字串
- 集合
- 方法
- JavaBean
- 關於閉包
字串#
說一個 Groovy 的特性,在 Groovy 中分號不是必須的,其單引號是雙引號都定義的是一個字串常量,不同之處是單引號是純粹的字串常量,不會對該字串裡面的表達式做運算,而使用雙引號定義的字串常量可以使用合法表達式做相關運算,測試代碼如下:
task stringTest{
//使用def關鍵字定義變量,
def str1 = "雙引號"
def str2 = '單引號'
println "雙引號定義的字串:"+str1
println "雙引號定義的字串:"+str1.class
println "單引號定義的字串:"+str2
//變量動態變化
str1 = true;
println "雙引號定義的字串:"+str1.class
//使用$運算符
println "雙引號定義的字串:${str1}"
//只有一個變量的時候可以省去中括號
println "雙引號定義的字串:$str1"
//單引號定義的字串不能使用表達式進行運算
println '單引號定義的字串:$str2'
}
下面是執行結果,參考如下:
PS E:\Gradle\study\Groovy> gradle stringTest
> Configure project :
雙引號定義的字串:雙引號
雙引號定義的字串:class java.lang.String
單引號定義的字串:單引號
雙引號定義的字串:class java.lang.Boolean
雙引號定義的字串:true
雙引號定義的字串:true
單引號定義的字串:$str2
BUILD SUCCESSFUL in 1s
集合#
Groovy 中也有集合的概念,主要看一下常用的 List、Map,下面將對 List 和 Map 常用操作進行介紹。
那麼如何在 Groovy 中定義 List 呢,Groovy 中的 List 的定義方式類似於 Java 中的數組,具體操作參考下面代碼:
task list{
//定義List
def list = [1,2,3,4,5,6];
def weekList = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日'];
println "list的類型:"+list.class
println "weekList的類型:"+weekList.class
//訪問集合裡面的元素
println '第一個元素:'+list[0]//訪問第一個元素
println '第二個元素:'+list[1]//訪問第二個元素,以此類推
println '最後一個元素:'+list[-1]//訪問最後一個元素
println '倒數第二個元素:'+list[-2]//訪問倒數第二個元素,以此類推
println '某個範圍內元素:'+list[2..4]//訪問某個範圍內元素,以此類推
//使用each遍歷集合中的元素
weekList.each{
//使用it作為迭代的元素變量,不能寫錯喔
println it
}
}
下面是上述代碼的執行結果,參考如下:
PS E:\Gradle\study\Groovy\ListMap> gradle list
> Configure project :
list的類型:class java.util.ArrayList
weekList的類型:class java.util.ArrayList
第一個元素:1
第二個元素:2
最後一個元素:6
倒數第二個元素:5
某個範圍內元素:[3, 4, 5]
星期一
星期二
星期三
星期四
星期五
星期六
星期日
BUILD SUCCESSFUL in 2s
那麼如何在 Groovy 中定義 Map 呢,Groovy 中的 Map 當然也是鍵值對,具體定義及操作參考下面代碼:
task map{
//定義Map
def map = ['name':'Groovy', 'age':10];
println "map的類型:"+map.getClass().name;
//訪問Map裡面的元素
println map.name;
println map['name'];
//遍歷Map中的元素
map.each{
println "Key:${it.key},value:${it.value}"
}
}
下面是上述代碼的執行結果,參考如下:
PS E:\Gradle\study\Groovy\ListMap> gradle map
> Configure project :
map的類型:java.util.LinkedHashMap
Groovy
Groovy
Key:name,value:Groovy
Key:age,value:10
BUILD SUCCESSFUL in 2s
關於 Groovy 的集合就了解這麼多。
方法#
Groovy 中的方法和 Java 中的方法類似,只是寫法上更加靈活,Groovy 中 return 不是必須的,在不寫 return 的時候,Groovy 會將最後一句代碼作為該方法的返回值。代碼塊指的是一段被花括號包圍的代碼,Groovy 中可將代碼塊作為一個參數進行傳遞,可以參考前面關於集合的遍歷部分,參考代碼如下:
task method{
//方法調用
methodA(1, 2)
methodA 1, 2
//獲取方法返回的結果
def a = methodA 10, 20
println '獲取方法返回的結果:'+a
//代碼塊作為參數傳遞
def list = [1,2,3,4,5];
list.each(
//閉包參數
{
// println it
}
)
//Groovy規定,如果方法的最後一個參數是閉包,可以直接放到方法外面
list.each(){
// println it
}
//簡寫方式
list.each{
println it
}
}
//方法的定義
def methodA(int a, int b){
println a + b
//Groovy中return語句不是必須的,默認將最後一句代碼的結果作為返回值
a + b
}
下面是上述代碼參考如下:
PS E:\Gradle\study\Groovy\Method> gradle method
> Configure project :
3
3
30
獲取方法返回的結果:30
1
2
3
4
5
BUILD SUCCESSFUL in 2s
JavaBean#
Groovy 中的 JavaBean 相較 Java 中的比較靈活,可以直接使用 javaBean. 屬性的方式獲取和修改 JavaBean 的屬性值,無需使用相應的 Getter、Setter 方法,直接看代碼:
task javaBean{
//Groovy中定義JavaBean
Student student = new Student()
student.name = "Groovy"
student.age = 10
student.setName("Gradle")
println "名字是:"+student.name
//不能調用Getter方法獲取值
// println "名字是:"+student.getName
println "年齡是:${student.age}"
println "分數是:"+student.score
}
class Student{
private String name
private int age
//定義的Getter方法所對應的屬性可以直接調用
public String getScore(){
100
}
//屬性的Getter、Setter方法
public String setName(String name){
this.name = name
}
public void getName(){
name
}
}
下面是上述代碼的執行結果:
PS E:\Gradle\study\Groovy\JavaBean> gradle javaBean
> Configure project :
名字是:Gradle
年齡是:10
分數是:100
BUILD SUCCESSFUL in 2s
閉包#
閉包是大多數腳本語言具有的一個特性,如 JavaScript、Groovy 等,閉包就是一個使用花括號包圍的代碼塊,下面來學習 Groovy 中的閉包,主要有兩部分:閉包及閉包參數傳遞和閉包委託。
閉包及其參數傳遞#
下面來看一下如何定義一個閉包以及相關參數的傳遞,直接上代碼:
task closure{
//自定義閉包的執行
mEach{
println it
}
//向閉包傳遞參數
mEachWithParams{m,n -> //m,n ->將閉包的參數和主體區分離開來
println "${m} is ${n}"
}
}
//1.定義一個方法,參數closure用於接收閉包
//2.閉包的執行就是花括號裡面代碼的執行
//3.閉包接收的參數就是閉包參數closure參數中的i,如果是一個參數默認就是it變量
def mEach(closure){
for(int i in 1..5){
closure(i)
}
}
//向閉包傳遞參數
def mEachWithParams(closure){
def map = ["name":"Groovy","age":10]
map.each{
closure(it.key, it.value)
}
}
上面代碼中定義了閉包以及如何進行閉包的參數的傳遞,當閉包只有一個參數時,默認就是 it,反之閉包有多個參數時,就需要將參數定義出來,具體可參考上述代碼,下面是執行結果:
PS E:\Gradle\study\Groovy\Closure> gradle delegate
> Configure project :
1
2
3
4
5
name is Groovy
age is 10
BUILD SUCCESSFUL in 2s
閉包委託#
Groovy 閉包的強大之處在於它支持閉包方法的委託,Groovy 的閉包有三個屬性:thisObject、owner、delegate,當在一個閉包中調用定義的方法時,由這三個屬性來確定該方法由哪個對象來執行,默認 owner 和 delegate 是相等的,其中 delete 是可以被修改的,Gradle 中閉包的很多功能都是通過修改 delegate 來實現的。下面通過定義一個閉包以及方法,通過打印來說明這三個屬性的一些區別:
//閉包的委託
task delegate{
new Delegate().test{
//Groovy閉包的三個屬性:thisObject、owner、delegate
println "thisObject:${thisObject.getClass()}"
println "owner:${owner.getClass()}"
println "delegate:${delegate.getClass()}"
//閉包默認it
println "閉包默認it:"+it.getClass()
//定義的方法,優先使用thisObject來處理
method()
//閉包中的方法
it.method()
}
}
def method(){
println "mththod in root:${this.getClass()}"
}
class Delegate{
def method(){
println "mththod in Delegate:${this.getClass()}"
}
//閉包
def test(Closure<Delegate> closure){
closure(this);
}
}
下面是上述代碼的執行結果,參考如下:
PS E:\Gradle\study\Groovy\Closure> gradle delegate
> Configure project :
thisObject:class build_3ajca04o1rprxygcsq0ajvt7i
owner:class build_3ajca04o1rprxygcsq0ajvt7i$_run_closure2
delegate:class build_3ajca04o1rprxygcsq0ajvt7i$_run_closure2
閉包默認it:class Delegate
mththod in root:class build_3ajca04o1rprxygcsq0ajvt7i
mththod in Delegate:class Delegate
BUILD SUCCESSFUL in 2s
當在閉包中調用方法 method () 時,發現是 thisObject 調用了 method () 方法,而不是 owner 或 delegate,說明閉包中優先使用 thisObject 來處理方法的執行,同時可以看到 owner 和 delegate 是一致的,但是 owner 比 delegate 的優先級要高,所以閉包中方法的處理順序是:thisObject > owner > delegate。
Gradle 中一般會指定 delegate 為當前的 it,這樣我們將可以通過 delegate 指定的對象來操作 it 了,下面是指定閉包的 delegate 並設置委託優先,讓委託的具體對象來執行其方法,下面是測試代碼:
task student{
configStudent{
println "當前it:${it}"
name = "Groovy"
age = 10
getInfo()
}
}
class Student{
String name
int age
def getInfo(){
println "name is ${name}, age is ${age}"
}
}
def configStudent(Closure<Student> closure){
Student student = new Student()
//設置委託對象為當前創建的Student實例
closure.delegate = student
//設置委託模式優先,如果不設置閉包內方法的處理者是thisObject
closure.setResolveStrategy(Closure.DELEGATE_FIRST)
//設置it變量
closure(student)
}
下面是上述代碼的執行結果,參考如下:
PS E:\Gradle\study\Groovy\Closure> gradle student
> Configure project :
當前it:Student@18f6d755
name is Groovy, age is 10
BUILD SUCCESSFUL in 2s
總結#
學習 Groovy 的目的還是為了加深對 Gradle 構建工具的理解,上面通過五個方面對 Groovy 有了初步的人認識,後續如果有需要再看 Groovy 的高級用法。