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
Groovy中,對List的使用作了一些簡化orm
task printList << {
def list = [1,3,5]
println list.getClass().name
println list[1]//訪問第二個元素
pringln list[-1]//訪問最後一個元素
}
複製代碼
打出來的結果是ArrayList,task的使用後續再講述對象
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)接口
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()
複製代碼