Groovy基础

<<Android Gradle权威指南》阅读笔记——Groovy基础

​ 本文讲述Groovy 基础Groovy是基于JVM虚拟机的一种动态语言,又在此基础上增加了很多动态类型和灵活特性,比如支持闭包,支持DSL,可以说它是一门非常灵活的动态脚本语言。

​ 每个Gradlebuild脚本文件都是Groovy脚本文件你可以在里面写任何符合Groovy语法的代码,比如定义类,声明函数,定义变量等;而Groovy又完全兼容Java,这就意味着你可以在build脚本文件里写任何的Java代码。


1. 字符串

Groovy中,单引号和双引号都可以定义一个字符串常量(Java里单引号定义一个字符),不同的是单引号标记的是纯粹的字符串常量,而不是对字符串里表达式做运算,单引号没有运算能力,双引号可以:

  • 类型:
task printStringClass << {
     def str1 = '单引号'
     def str2 = "双引号"
    ​
     println "单引号定义的字符串类型:"+str1.getClass().name
     println "双引号定义的字符串类型:"+str2.getClass().name
    }
./gradlew printStringClass 输出
    Task :printStringClass
    单引号定义的字符串类型:java.lang.String
    双引号定义的字符串类型:java.lang.String</pre>
  • 运算
task printStringVar << {
     def name = "张三"
    ​
     println '单引号的变量计算:${name}'
     println "双引号的变量计算:${name}"
    }</pre>
./gradlew printStringVar 输出
 Task :printStringVar
    单引号的变量计算:${name}
    双引号的变量计算:张三

2. 集合

Groovy完全兼容了Java的集合,并进行了扩展,使操作变得更容易。

  • List

    Grroovy中实现List非常简单,同时还提供了下标索引负下标范围索引迭代操作(each)

task printList << {
     def numList = [1,2,3,4,5,6];
     println numList.getClass().name //输出时可以看出 numList 是一个 ArrayList
    ​
     println numList[1]//访问第二个元素 下标索引 下标从 0 开始
     println numList[-1]//访问最后一个元素 负下标 
     println numList[-2]//访问倒数第二个元素 负下标
     println numList[1..3]//访问第二个到第四个元素 范围索引 由”.."分开
    ​
     numList.each{//迭代操作
     println it //it 正在迭代的元素,这里涉及闭包的知识,下文会讲解
     }
    }
./gradlew printList 输出
Task :printList
    java.util.ArrayList
    2
    6
    5
    [2, 3, 4]
    1
    2
    3
    4
    5
    6
  • Map

    Map的用法和List类似,区别在于它的值是K:V`键值对

task printMap << {
     def mapl = ['width':1920,'height':1080]
     println mapl.getClass().name //输出可以看出mapl是一个LinkedHashMap
    ​
     //访问可以采用map[key]或者map.key两种方式
     println mapl['width']
     println mapl.height
    ​
     mapl.each{//迭代操作
     println "Key:${it.key},Value:${it.value}"//此处的it是一个Map.Entry实例
     }
    }
./gradlew printMap 输出
 Task :printMap
    java.util.LinkedHashMap
    1920
    1080
    Key:width,Value:1920
    Key:height,Value:1080

关于集合的更多方法后续会补充,有兴趣的可以自行先了解

3. 方法

通过了解Groovy方法和Java方法的不同,更利于我们明白Gradle脚本里的代码

  • 括号可以省略

    Groovy调用一个方法比Java灵活的多,可以省略(),在定义DSL时非常有用并且书写方便

task invokeMethod << {
     //这两种调用方式结果一直,但第二种更简洁
     methodl (1,2)
     methodl 1,2
    }
    ​
    def methodl(int a, int b){
     println a+b
    }
./gradlew invokeMethod 输出
 Task :invokeMethod
    3
    3
  • return 可以不写

    Groovy在没有return时,会将方法执行过程中的最后一句作为返回值

task printMethodReturn << {
     def add1 = method2 1,2
     def add2 = method2 5,3
     println "add1:${add1},add2:${add2}"
    }
    ​
    def method2(int a,int b){
     if(a>b){
       a //执行到此处 返回a
     }else{
       b //执行到此处 返回b
     }
    }
./gradlew printMethodReturn 输出
 Task :printMethodReturn
    add1:2,add2:5
  • 代码块可以作为参数传递

    通过each方法,我们可以直接的理解这个问题

    //最初的写法
    numList.each({println it})
    ​
    //经过格式化
    numList.each({
       println it
    })
    ​
    //Groovy中方法的最后一个参数为闭包,可以放到外面
    numList.each(){
       println it
    }
    ​
    //去掉方法的括号
    numList.each{
       println it
    }

4. JavaBean

JavaBean中繁琐的getter/setterGroovy中得到了很大改善

task helloJavaBean << {
   Person p = new Person()
​
   println "名字是:${p.name}"//此时name为赋值,返回null
   p.name = 'tom'
   println "名字是:${p.name}"//已赋值,返回tom
   println "年龄是:${p.age}"//未定义成员变量时,通过getAge()方法也可获取age,但不能修改值
}
​
class Person{
   private String name
   public int getAge(){
     12
 }
}

./gradlew helloJavaBean 输出

 Task :helloJavaBean
名字是:null
名字是:tom
年龄是:12

5. 闭包

闭包是Groovy的一个非常重要的特性,可以说他是DSL的基础。

task helloClosure << {
 //使用自定义闭包
   customEach {
     println it
   }

​
 //多个参数
   eachMap {k,v ->
     println "${k} is ${v}"
    }
}
​
def customEach(closure){//唯一参数,用于接收一个闭包(代码块)
   //模拟一个集合,开始迭代
   def numList = [1,2,3]
   numList.each{
     closure(it)
   }
}
​
def eachMap(closure){//此处的闭包传递两个参数k v
   def mapl = ["name":"tom","age":18]
   mapl.each{
     closure(it.key,it.value)
   }
}

./gradlew helloClosure 输出

 Task :helloClosure
1
2
3
name is tom
age is 18
  • 闭包委托

Groovy闭包的强大之处在于它支持闭包方法的委托。Groovy的闭包有thisObject,owner,delegate三个属性,当你在闭包内调用方法时,由它们来确定使用哪个对象来处理。默认情况下delegateowner是相等的,但是delegate是可以被修改的,这个功能是非常强大的,Gradle中的很多功能都是通过修改delegate实现的。

task helloDelegate << {
   new Delegate().test{
     println "thisObject:${thisObject.getClass()}" //thisObject优先级最高
     println "owner:${owner.getClass()}"//owner优先级次之
     println "delegate:${delegate.getClass()}"
     //delegate优先级最低,但是owner==delegate
     //闭包内方法的执行顺序:thisObject>owner>delegate
     method3()
     it.method3()
   }
}
​
def method3(){
   println "Context this:${this.getClass()} in root"
   println "method3 in Delegate"
}
​
class Delegate{
   def method3(){
     println "Delegate this:${this.getClass()} in Delegate"
     println "method3 in Delegate"
   }
​
   def test(Closure<Delegate> closure){
     closure(this)
   }
}

./gradlew helloDelegate 输出

 Task :helloDelegate
thisObject:class build_edqlj0scrowqqm8jgfgirxcz4
owner:class build_edqlj0scrowqqm8jgfgirxcz4$_run_closure10
delegate:class build_edqlj0scrowqqm8jgfgirxcz4$_run_closure10
Context this:class build_edqlj0scrowqqm8jgfgirxcz4 in root
method3 in Delegate
Delegate this:class Delegate in Delegate
method3 in Delegate

DSL中,比如Gradle,我们会指定delegate为当前的it,这样我们在闭包内就可以对该it进行配置,或调用其方法。

task configClosures << {
   man {//在闭包类直接对Man实例配置
     manName = "tom"
     manAge = 19
     dumpMan()
   }
}
​
class Man{
   String manName
   int manAge
​
   def dumpMan(){
     println "name is ${manName},age is ${manAge}"
   }
}
​
def man(Closure<Person> closure){
   Man p = new Man();
   //设置委托对象为当前创建的Man实例
   closure.delegate = p 
   //委托模式优先
   closure.setResolveStrategy(Closure.DELEGATE_FIRST);
   closure(p)
}

./gradlew configClosures 输出

 Task :configClosures
name is tom,age is 19

6. DSL

DSL(Domain Specific Language)——领域特定语言(专门关注某一领域的语言)

Gradle就是一门DSL,它基于Groovy专门解决自动化构建的DSL

到这Groovy基础就简单介绍完了,后续我们再学习新的Gradle知识,欢迎持续关注

原文链接 更多类容

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容