Gradle系列之Groovy基础

这篇博客介绍了Groovy的基础知识,包括数据类型、容器类如List、Map和Range,以及Groovy的特性,如自动getter/setter和默认公共访问权限。重点讲述了闭包的不同策略,如OWNER_FIRST、DELEGATE_FIRST等,并通过示例展示了闭包在文件操作中的应用。此外,还提及了Groovy的特殊符号和as操作符的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Gradle系列之Groovy基础
Gradle系列之Gradle基础
Gradle系列之自定义插件
Android构建流程(Android Plugin)源码解析系列一:主流程

数据类型


groovy中没有基本数据类型,它任务任何事物都是对象;它会将基本数据类型包装成其对应的包装类型

groovy中容器类


  • List: 其底层对应java的List接口,一般用ArrayList作为实现类
  • Map: 底层对应java的LinkedHashMap
  • Range : Groovy对List的一种拓展

List

List的创建和修改

    def emptyList = [] // 创建一个空的list
    def list = ['hello', 100, 'word'] // List中可以存储多种数据类型
    list[2] = 200 // 修改
    list << 'fuck' // 新增
    println list[2]
    println list.size()

List的遍历

    for (def i=0; i< list.size(); i++){
        println list[i]
    }

    // each 遍历 list
    list.each {
        println it
    }

    // for in 遍历
    for (v in list){
        println v
    }

Map

注意: key必须用字符串,如果使用的变量名,那么会将其识别为字符串(当前变量名的字符串,即使这个变量可以获取)
map的操作

    def emptyMap = [:] // 创建空的map
    def map = ['key1': 100, 'key2':'hello']
    // 通过key获取value
    def val1 = map.key1
    def val2 = map['key2']
    // 添加新元素
    map['key'] = true

map的遍历

    map.each {key, val ->
        println 'map each : key : '+key+"; value : ${val}"
    }

    map.each {
        println "map each(no params) : key: ${it.key}, value : ${it.value}" // 注意: ${}只能在 双引号中才能使用
    }

Range

    def range1 = 1..5 // 包含了 1,2,3,4,5
    def range2 = 1..<5 // 包含 1,2,3,4(不包括5)
    println range1.from
    println range1.to
    range1.each {
        println "Range iterator : ${it}"
    }

groovy的特性

  • 会为对象的成员变量,自动增加getter和setter;所以我们查看api的时候,往往都会查到其成员变量对应get和set方法,我们 对象.成员变量,就是调用它的getter方法
  • 默认访问权限是public

闭包

groovy里面的闭包,其实就是将一个方法作为一个参数传入到一个方法里面;它实现的功能和java中的回调函数类似。
我们先看闭包的一个,简单的例子

class Person {
    String name
    int age

    def printPerson() {
        println "name is ${name}, age is ${age}"
    }
}

def person(Closure<Person> closure) {
    Person p = new Person()
    // 定义闭包中 执行对象
    println closure.getResolveStrategy() // 默认 OWNER_FIRST
    closure.delegate = p // 设置委托对象
    closure.setResolveStrategy(Closure.DELEGATE_FIRST) // 修改委托策略
    closure() // 执行委托
}

def printPerson() {
    println '当前构建上下文 print person'
}

task configClosure << {
    println 'execute config closure'
    person {
        // 因为上面的方法中,将委托策略改成了 DELEGATE_FIRST,也就是将作用域设置成了委托对象,也就是Person的对象
        name = 'xiaoming'
        age = 20
        printPerson() // 这里执行的是Person对象的方法
    }
}

关于闭包的重点,就是传入到方法中的闭包的作用域,不同的作用域,闭包中的代码执行不同的逻辑;关于闭包的策略,groovy提供了几种策略。

  • OWNER_FIRST : 默认,当前对象优先,当前方法所在对象的作用域
  • DELEGATE_FIRST: 委托对象优先;如果当前有委托对象,那么优先使用委托对象作为当前闭包的作用域范围;如果没有,那么使用当前方法的作用域对象。
  • OWNER_ONLY : 只从当前方法对象的作用域内执行,如果没有找到对应的成员,直接抛出异常
  • DELEGATE_ONLY: 只从委托对象的作用域内执行,如果没有知道对应的成员,直接抛出异常
  • TO_SELF : 闭包会被编译成java中的类,此种情况会从当前闭包所在类的作用域内寻找对应的成员,如果没有,直接抛出异常

下面例子均来自官方文档

OWNER_FIRST

class Test {
    def x = 30
    def y = 40

    def run() {
        // 默认 OWNER_FIRST
        def data = [x: 10, y: 20]
        // 默认 owner_first : 设置委托对象无用
        def cl = {
            y = x + y
        }
        cl.delegate = data
        cl()
        println x == 30 // true
        println y == 70 // true
        println data == [x: 10, y: 20] // true
    }
}

DELEGATE_FIRST

class Test {
    def x = 30
    def y = 40

    def run() {
        def data = [ x: 10, y: 20 ]
        def cl = { y = x + y }
        cl.delegate = data
        cl.resolveStrategy = Closure.DELEGATE_FIRST
        cl()
        assert x == 30 // true
        assert y == 40 // true
        assert data == [x:10, y:30] // true
    }
}

OWNER_ONLY

class Test {
    def x = 30
    def y = 40

    def run() {
        // OWNER_ONLY : 这种模式就是,即使你设置了delegate也没有用, 如果当前OWNER没有那么就会报错;并不会去delegate里面去寻找
        // 下面案例: 如果Test没有 z, 就会报错
        def data = [ x: 10, y: 20, z: 30 ]
        def cl = { y = x + y + z } // 这里抛出异常
        cl.delegate = data
        cl.resolveStrategy = Closure.OWNER_ONLY
        cl()
        println x
        println y
        println data
    }
}

注意: 如果上面的case,改成OWNER_FIRST,就不会抛出异常,并且只有在OWNER范围内没有找到的z,才会从委托对象去查找。输出结果如下:
30
100
[ x: 10, y: 20, z: 30 ]

DELEGATE_ONLY

这种策略就是只会从委托对象范围内寻找,如果没有找到,抛出异常,这里就不放例子了。

TO_SELF

class Test {
    def x = 30
    def y = 40

    def run() {
        def data = [ x: 10, y: 20, z: 30 ]
        def cl = { y = x + y } // 抛出异常,因为当前闭包对象里面, x和y都没有
        cl.delegate = data
        cl.resolveStrategy = Closure.TO_SELF
        cl()
        println x
        println y
        println data
    }
}

闭包的一个特性

如果一个方法的最后一个参数是一个闭包,那么调用这个方法的时候,可以将闭包放在外面。例子如下

def demo(int a, Closure closure){}
demo(2){
    // 闭包代码
}
//上面等价于
demo(2, {
    // 闭包代码
})

文件操作

def file = new File('app/a.txt') // 当前目录是 当前项目的根目录
    // 逐行读取
    file.eachLine {line, lineNo ->
        println "${lineNo} ${line}"
    }

    // 一次性获取
    byte[] bytes = file.getBytes()

    // 以流的方式读取 (一次性获取);;  好处: 无需处理流的关闭操作
    file.withInputStream {is ->
        println is.getText()
    }

    def writeFile = new File('app/b.txt')
    // write() 覆盖内容;;   append() 向尾部追加内容
    writeFile.withOutputStream { os ->
        file.withInputStream { is ->
            os << is  // 重载了<< 符号,将输入流的数据传递给输出流
        }
    }

可以看出groovy对io的操作简化的很舒适。

特殊符号

groovy的特殊服务,能够简化我们很多代码。

    def list = ['h', 'hello', 'jjj']

    println list?.size()  // ?. 相当于 判断list不为null,才执行size()方法, 否则直接返回null

    println list*.size()  // *. 相当于 用在集合对象里面,对里面每一个元素执行 size()方法,然后将返回值组成新的 list 返回

    // .& 相当于 将一个对象的 方法 转变成 closure 然后传递
    list.each(this.&printItem)

    // .@ 相当于 直接获取一个 对象中的 变量;; 注意 .变量名 调用的是此变量的 gettter方法

    def person = new Person(name : '小明')
    println person.name // 调用name的 getter方法
    println person.@name


    // ?: 相当于 java中三目运算符, 但是判断条件是前面的内容
    println person.@age ?: 'age is null'

as操作符

as操作符相当于java中的强制类型转换,它也支持数组和List之间的转换。
当然,groovy,可以直接赋值,不使用as操作符也可以。

String[] strs = ['a', 'b']
List list = strs as List
List list2 = strs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值