Groovy基础

作者: XiMiMax | 来源:发表于2018-06-30 11:26 被阅读12次

    <<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知识,欢迎持续关注

    原文链接 更多类容

    相关文章

      网友评论

        本文标题:Groovy基础

        本文链接:https://www.haomeiwen.com/subject/yoltuftx.html