Gradle學習(一):你應該知道的Groovy

Groovy是基於JVM的虛擬機的一門語言,語法和Java很類似,而且徹底兼容Java。Java上能寫的代碼在Groovy中是能夠運行的。但同時Groovy引入了閉包,增長了許多特性使用起來較爲靈活方便。Gradle腳本使用的是Groovy語法,具有Groovy基礎對於學習和使用Gradle是十分重要的。本篇將簡要寫一些經常使用的Groovy語法相關知識,便於看懂Gradle腳本的一些經常使用寫法java

字符串

Groovy中的字符串有三種寫法: 單引號寫法:markdown

def singleStr = 'single'
複製代碼

雙引號寫法:閉包

def doubleStr = "double"
複製代碼

三引號寫法:學習

def threeStr = '''Three'''
複製代碼

三者的區別:this

單引號寫法和Java的字符串相同,singleStr.class == java.lang.String 雙引號寫法正常狀況下和Java字符串相同,但支持插值,當插值時,類型就不等同於Java.lang.String,而是groovy.lang.GString; 即當 def doubleStr = "double"時,類型是java.lang.String 當def doubleStrs = "double ${var}"時,類型是groovy.lang.GString 三引號寫法也是java.lang.String,不支持插值。但三引號內支持回車換行的寫法,而不須要使用\r\nspa

集合

Groovy的集合code

List

Groovy中,對List的使用作了一些簡化orm

task printList << {
	def list = [1,3,5]
	println list.getClass().name
	println list[1]//訪問第二個元素
	pringln list[-1]//訪問最後一個元素
}
複製代碼

打出來的結果是ArrayList,task的使用後續再講述對象

Map

task printlnMap << {
	def map = ['width':30, 'height':40]
	println map.width
	println map['height']
}
複製代碼

方法

實參括號是能夠省略的

def addMethod(int a, int b){
	println a+b
}
task invokeMethod << {
	addMethod(3,5)
	addMethod 3, 5
}
複製代碼

對比Android中常寫的如compileSdkVersion 28,其實是調用方法compileSdkVersion(28)接口

return是能夠省略的

def compileMethod(int a, int b) {
	if (a > b) {
		a
	} else {
		b
	}
}
task invokeCompile << {
	def a = compileMethod(3, 5)
	println "${a}"
}
複製代碼

當沒寫返回值時,最後一句語句的值便是返回值

閉包

閉包其實是一段代碼段,閉包不是Groovy初創,可是Groovy支持使用閉包

基本用法

def printClosure(closure){
	for (int i = 0; i < 10; i++) {
		closure(i)
	}
}
task closureMethod << {	
	printClosure {
		println it
	}
}
複製代碼

上述代碼運行closureMethod時,實際上運行的方法爲printlnClosure(閉包)上述寫法是省略了參數的括號,it是傳入閉包的參數

傳遞參數

def printlnParams(closure){	
	int x = 5
	int y = 6
	closure(x,y)
}
task closureParamsMethod << {
	printlnParams {
		k,v->
		println "x=${k},y=${v}"
	}
}
複製代碼

閉包委託

groovy的閉包有三個屬性thisObject,owner,delegate. this,owner是肯定的不可修改,而delegate是可修改的,能夠靈活使用 this和owner一般狀況下是一致的,this指的是離閉包最近的對象(不包含閉包),owner表明閉包定義處最近的對象能夠是閉包,delegate默認與owner一致但能夠修改。 所以this和owner在閉包中定義閉包的狀況下會不一樣,其餘狀況下是一致的,而delegate由於可修改,就取決於修改成什麼了

class Person {
	private String name
	int personAge
	def dumpPerson() {
		println "name is ${name}, age is ${personAge}"
	}
}
def person(Closure<Person> closure){
	Person p = new Person()
	closure.delegate = p
	//委託模式優先
	closure.setResolveStrategy(Closure.DELEGATE_FIRST);
	closure(p)
}
//使用
task configClosure << {
	person {
		name="Breeze"
		personAge=20
		dumpPerson()
	}
}
複製代碼

閉包在各類配置中用的很是多,尤爲是閉包委託的靈活應用

面向對象

定義類

/**
*Groovy中默認都是public,而且默認實現的是GroovyObject接口
**/
class Person {
	String name
	Integer age
	//def返回類型實際上就等同於Object
	def increaseAge(Integer years) {
		this.age += years
	}
}
複製代碼

使用類

def person = new Person(name :'Breeze', age:25)
//實際上調用的是get方法,這點與java不一樣,不管是點仍是get/set實際上調用的都是get/set
println person.name
複製代碼

接口

//只能定義public的方法
interface IAction {
	void doSomething()
}
複製代碼

trait類型,相似於java中的抽象類

trait DefaultAction {
	abstract void eat()
	void play() {
		println 'I can play'
	}
}
複製代碼

方法:Groovy中的方法和Java中區別比較大,當調用一個方法,Java類中不存在時,編譯時就會報錯,但Groovy不會,Groovy有一套調用方法的流程,只有當整個流程都不能運行該方法纔會報錯 流程:類中是否有此方法->metaClass中是否有此方法->是否重寫了methodMissing()方法->是否重寫了invokeMethod()方法 案例一:

def person = new Person(name:'Breeze', age:25)
//報錯,missingMethod,由於上述流程都不能執行方法
person.cry()
複製代碼

案例二,改造Person類(invokeMethod):

class Person {
	String name
	Integer age
	//def返回類型實際上就等同於Object
	def increaseAge(Integer years) {
		this.age += years
	}
	def invokeMethod(String name, Object args){
		return "the method is ${name}, the params is ${args}"
	}
}
//使用
def person = new Person(name:'Breeze', age:25)
//不報錯,而且打印出the method is cry, the params is []
println person.cry()
複製代碼

案例三 改造Person (methodMissing方法重寫)

class Person {
	String name
	Integer age
	//def返回類型實際上就等同於Object
	def increaseAge(Integer years) {
		this.age += years
	}
	def invokeMethod(String name, Object args){
		return "the method is ${name}, the params is ${args}"
	}
	def methodMissing(String name, Object args){
		return "the method ${name} is missing"
	}
}
//使用
def person = new Person(name:'Breeze', age:25)
//不報錯,而且打印出the method is missing
println person.cry()
複製代碼

案例四 改造Person(metaClass使用)

class Person {
	String name
	Integer age
	//def返回類型實際上就等同於Object
	def increaseAge(Integer years) {
		this.age += years
	}
	def invokeMethod(String name, Object args){
		return "the method is ${name}, the params is ${args}"
	}
	def methodMissing(String name, Object args){
		return "the method ${name} is missing"
	}
}
//使用
//使用metaClass增長屬性
Person.metaClass.sex = 'male'
//使用metaClass增長方法
Person.metaClass.nameUpperCase = {
	-> name.toUpperCase()
}
//爲類增長靜態方法
Person.metaClass.static.createPerson = {
	String name, int age -> new Person(name:name, age: age)
}
def person = new Person(name:'Breeze', age:25)
//正確打印出sex屬性值
println person.sex
person.nameUpperCase()
pringln person.name
def person3 = Person.createPerson('Breeze', 20)
複製代碼

但這種寫法只能在當前腳本用,不能在整個項目中用 若是要在整個項目中使用,須要在調用metaClass前執行

ExpandoMetaClass.enableGlobally()
複製代碼
相關文章
相關標籤/搜索