Gradle系列之Groovy基礎篇

原文發於微信公衆號 jzman-blog,歡迎關注交流。java

上一篇學習了 Gradle 的入門知識,Gradle 基於 Groovy,今天學習一下 Groovy 的基礎知識,Groovy 是基於 JVM 虛擬機的一種動態語言,語法與 Java 語法相似,Groovy 徹底兼容 Java,每一個 Gradle 文件都是一個 Groovy 腳本文件,Gradle 文件基於 Groovy 語法,而 Groovy 又兼容 Java,故能夠在 Gradle 文件中寫 Java 代碼,在此基礎上增長了不少新特性,如支持閉包、DSL等,能夠說 Groovy 是一門很是靈活的動態腳本語言,閱讀本文以前能夠先閱讀下面這篇文章:數組

下面針對 Gradle 來學習一下 Groovy 的一些基礎知識。微信

  1. 字符串
  2. 集合
  3. 方法
  4. JavaBean
  5. 關於閉包

字符串

說一個 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 經常使用操做進行介紹。post

那麼如何在 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 固然也是鍵值對,具體定義及操做參考下面代碼:gradle

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}"
	}
}

複製代碼

下面是上述代碼的執行結果,參考以下:ui

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 的高級用法。能夠關注公衆號:jzman-blog,一塊兒交流學習。