美文网首页
gradle7 从上手到实践之 groovy 基础语法

gradle7 从上手到实践之 groovy 基础语法

作者: ddu_ | 来源:发表于2022-07-05 10:30 被阅读0次

    如何创建一个 groovy 项目?
    使用 idea 按照下图的选项创建一个新项目:


    创建 groovy 项目

    1 变量

    //无基本类型,均为对象类型
    //不用写分号
    int x = 10
    println x.class
    
    //可以无需指定类型
    def y = 2
    def z = 3.14
    

    变量部分核心要点:

    • 没有基本变量,都是包装类
    • 语句结尾没有分号
    • 定义变量可以不指定类型,由编译器自动推断类型

    2 字符串

    • 单引号与 java 中的字符串类似
    • 双引号字符串可以使用 ${} 引用表达式的值
    • 三引号字符串自带格式
    //单引号
    def name = 'a single string'
    //双引号,可扩展字符串
    def name2 = "simple string"
    def sayName2 = "Hello ${name2}" 
    def sum = "The sum of 2 and 3 equals ${2 + 3}"
    //三引号,格式不变
    def name3 = '''\
    line one
    line two
    line three
    '''
    
    /字符 串的填充
    def str = "groovy Hello"
    println str.center(8, 'a') //agroovya
    
    //padLeft padRight
    println str.padLeft(8, 'a') //aagroovy
    
    //字符串的比较
    def str2 = 'Hello'
    println str.compareTo(str2)
    println str > str2
    
    //字符获取
    println str.charAt(0)
    println str[0]
    println str[0..1]
    
    //减法
    println str.minus(str2)
    println str - str2
    
    //字符串倒叙
    println str.reverse()
    //字符串首字母大写
    println str.capitalize()
    //字符串是否能装换为数字
    println str.isNumber()
    
    

    3 流程控制

    //switch
    def x = 1.23
    def result
    
    switch (x) {
        case 'foo'
            result = 'foo'
            break
        case [4,5,6,'inlist'] //列表
            result = 'list'
            break
        case 12..30:        //范围
            result = 'range' 
            break
        case BigDecimal:    //类型
            result = 'bigdecimal'
            break
        default: 
            result = 'default'
            break
    }
    
    println result
    
    //for
    def sum = 0
    for(i in 0..9) {
        sum += i
    }
    println sum
    
    for(i in [1,2,3,4,5,6,7,8,9]) {
        sum  += i
    }
    
    for(i in ['lili':1,'lucky':2,'xm':3]) {
        sum += i.value
    }
    
    

    4 闭包

    闭包就是一段可以执行的代码,可以有输入参数,有返回值

    //无参数情况
    def clouser = { println 'Hello groovy'}
    clouser.call()
    clouser()
    
    //有参数的情况
    def clouser2 = { String name -> "Hello ${name}" }
    clouser2.call("groovy")
    clouser2("groovy")
    
    //多个参数
    def clouser3 = { String name, int age -> "Hello ${name}, my age is ${age}" }
    clouser3.call("groovy",4)
    clouser3("groovy",4)
    
    //it的作用
    def clouser4 = {
        println "Hello ${it}"
    }
    clouser4("groovy")
    
    def clouser5 = { String name ->
        return "Hello ${name}"
    }
    println(clouser5('Groovy'))
    
    //闭包的返回值
    def clouser5 = { String name ->
        "Hello ${name}" //最后一行就是返回值
    }
    println(clouser5('Groovy'))
    
    //闭包组合 rightshift: >>    leftshift: <<
    //文档中示例
    def twice = { a -> a * 2 }
    def thrice = { a -> a * 3 }
    def times6 = twice >> thrice
    // equivalent: times6 = { a -> thrice(twice(a)) }
    assert times6(3) == 18
    
    def twice = { a -> a * 2 }
    def thrice = { a -> a * 3 }
    def times6 = thrice << twice
    // equivalent: times6 = { a -> thrice(twice(a)) }
    assert times6(3) == 18
    
    //一个更为清晰的实例
    def add = { a -> a + 5 }
    def mult = { a -> a * 4 }
    def rightShift = add >> mult//先+再*
    def leftShift = add << mult//先*再+
    assert rightShift(3) == 32
    assert leftShift(3) == 17
    

    5 闭包与字符串

    方法的最后一个参数是闭包,可以不写在括号中

    String str = 'the 2 and 3 is 5'
    
    str.each { String temp -> 
        println temp
    }
    
    str.find { String s -> 
        s.isNumber()
    }
    
    def list = str.findall { String s -> 
        s.isNumbner 
    }
    println list.toListString()
    
    def result = str.any { String s -> 
        s.isNumber
    }
    println result //返回 true
    
    def result = str.every { String s -> 
        s.isNumber()
    }
    println result //返回 false
    
    def list2 = str.collect { it.toUpperCase()}
    println list2.toListString()
    

    6 闭包进阶

    在闭包内部可以访问闭包的参数,也可以访问很多其他的变量和函数,比如 gradle 脚本中的依赖:

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
        }
    }
    

    dependencyResolutionManagement 是一个方法,其参数是一个闭包。闭包内部调用了很多方法,那这些方法是哪里来的呢?
    要知道这些方法从哪里来?我们需要理解 this, owner, delegate:

    • this: refers to the instance of the class that the closure was defined in.
    • owner: is the same as this, unless the closure was defined inside another closure in which case the owner refers to the outer closure.
    • delegate: is the same as owner. But, it is the only one that can be programmatically changed, and it is the one that makes Groovy closures really powerful.

    当在闭包内访问一个变量时,闭包查找这个变量的顺序是:

    • 闭包内部
    • this
    • owner
    • delegate

    可以使用 resolvedStrategy 方法改变这个顺序,这个方法接受的参数有(了解即可,一般都不用):

    • Closure.OWNER_FIRST
    • Closure.DELEGATE_FIRST
    • Closure.OWNER_ONLY
    • Closure.DELEGATE_ONLY

    为加深理解,下面来看几个示例:

    //理解三个引用的指向
    class MyClass {
      def outerClosure = {
        println this.class.name    // outputs MyClass
        println owner.class.name    // outputs MyClass
        println delegate.class.name  //outputs MyClass
        def nestedClosure = {
          println this.class.name    // outputs MyClass
          println owner.class.name    // outputs MyClass$_closure1
          println delegate.class.name  // outputs MyClass$_closure1
        }
        nestedClosure()
      }
    }
    def closure = new MyClass().outerClosure
    closure()
    
    
    
    //理解变量的访问顺序
    class MyClass {
      String myString = "myString1"
      def outerClosure = {
        println myString;     // outputs myString1
        def nestedClosure = {
           println myString;  // outputs myString1
        }
        nestedClosure()
      }
    }
    MyClass myClass = new MyClass()
    def closure = new MyClass().outerClosure
    closure()
    println myClass.myString
    
    
    
    
    //理解变量的访问顺序
    class MyClass {
      def outerClosure = {
        def myString = "outerClosure";     
        def nestedClosure = {
           println myString;  // outputs outerClosure
        }
        nestedClosure()
      }
    }
    MyClass myClass = new MyClass()
    def closure = new MyClass().outerClosure
    closure()
    
    
    
    
    //理解 delegate 的作用
    class MyOtherClass {
      String myString = "I am over in here in myOtherClass"
    }
    class MyClass {
      def closure = {
        println myString
      }
    }
    MyClass myClass = new MyClass()
    def closure = new MyClass().closure
    closure.delegate = new MyOtherClass()
    closure()   // outputs: "I am over in here in myOtherClass"
    
    
    
    //理解 delegate 的作用
    class MyOtherClass {
      String myString = "I am over in here in myOtherClass"
    }
    class MyOtherClass2 {
      String myString = "I am over in here in myOtherClass2"
    }
    class MyClass {
      def closure = {
        println myString
      }
    }
    MyClass myClass = new MyClass()
    def closure = new MyClass().closure
    closure.delegate = new MyOtherClass()  
    closure()     // outputs: I am over in here in myOtherClass
    closure = new MyClass().closure
    closure.delegate = new MyOtherClass2() 
    closure()     // outputs: I am over in here in myOtherClass2
    

    有了上面的基础,我们把省略的源码补充完整:

    dependencyResolutionManagement { DependencyResolutionManagement management ->
        management.repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        management.repositories { RepositoryHandler handler ->
            handler.google()
            handler.mavenCentral()
        }
    }
    

    7 数据结构

    List:

    def list = [1,2,3,4,5]              //ArrayList
    def array = [1,2,3,4,5] as int[]    //定义一个数组
    int[] array2 = [1,2,3,4,5]
    
    def list2 = new ArrayList<Integer>()
    list.add(1)
    list.add(2)
    list.add(3)
    
    //排序
    def sortList = [6,-3,9,2,-7,1,5]   
    //方法一,来至 java
    Comparator mc = { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 }
    Collections.sort(sortList, mc)
    println sortList
    //方法二,来至 Groovy
    sortList.sort()
    println sortList
    
    sortList.sort { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1  }
    
    def sortStringList = ['abc', 'z', 'Hello', 'groovy', 'java']
    sortStringList.sort { return it.size()} //根据长度排序
    
    //查找
    def findList = [-3, 9, 6, 2, 4, 5, 7]
    int result = findList.find {return it % 2 == 0}
    println result
    
    def result = findList.findAll {return it % 2 != 0}
    
    def result = findList.any {  //返回 true
      return it % 2 != 0
    }
    
    def result = findList.every { return it % 2 == 0}
    println result
    
    findList.min()  //查找最小值
    findList.max()  //查找最大值
    
    findList.min {return Math.abs(it)} //查找绝对值最小
    
    findList.count {
      return it % 2 == 0
    }
    

    Map:

    //Map
    //定义和初始化
    def map = new HashMap()
    def colors = [red:'ff0000', green:'00ff00', blue:'0000ff']
    //成员访问与赋值
    colors['red']
    colors.red 
    colors.yellow = 'ffff00'
    println colors.toMapString()
    colors.complex = [a : 1, b : 2] 
    
    def students = [
            1: [number: '0001', name: 'Bob',
                score : 55, sex: 'male'],
            2: [number: '0002', name: 'Johnny',
                score : 62, sex: 'female'],
            3: [number: '0003', name: 'Claire',
                score : 73, sex: 'female'],
            4: [number: '0004', name: 'Amy',
                score : 66, sex: 'male']
    ]
    
    //遍历
    stdudents.each { def student ->
        println "the key is ${student.key}, " +
                "the value is ${student.value}"
    }
    
    stdudents.eachWithIndex { def student, int index ->
        println "the index is ${index} " +
                "the key is ${student.key}, " +
                "the value is ${student.value}"
    }
    
    students.each { key, value ->
         println "the key is ${key}, " +
                "the value is ${value}"
    }
    
    students.eachWithIndex { key, value, index ->
          println "the index is ${index} " +
                "the key is ${student.key}, " +
                "the value is ${student.value}" 
    }
    
    //查找
    def entry = students.find { def student ->
        return student.value.score >= 60
    }
    println entry
    
    def entrys = students.findAll { def student ->
        return student.value.score >= 60
    }
    
    def count = students.count {def student ->
        return student.value.score >= 60
    }
    
    def names = students.count {def student ->
        return student.value.score >= 60
    }.collect {
      return it.value.name
    }
    
    
    def group = students.groupBy { def student -> 
        return student.value.score >= 60 ? '及格' : '不及格'
    }
    println group.toMapString()
    
    def sort = student.sort{ def student1, def student2 -> 
        Number score1 = student1.value.score
        Number score2 = student2.value.score
        return score1 == score2 ? 0 : score1 < score2 ? -1 : 1 
    }
    println sort.toMapString()
    

    Range:

    def range = 1..10
    println range[0]
    println range.contains(10)
    println range.from
    println range.to
    
    range.each {
      println it
    }
    
    for(i in range) {
      println i
    }
    
    def getGrade(Number number) {
      def result
      switch(number) {
        case 0..<60:
            result = '不及格'
            break
        case 60..<70
            result = '及格'
            break
        case 70..<80
            result = '良好'
            break
        case 80..100
            result = '优秀'
            break
      }
    }
    

    8 文件操作

    def file = new File('../../GroovySpecification.iml')
    
    file.eachLine { line ->
       println line
    }
    
    def text = file.getText()
    println text
    
    def result = file.readLines()
    
    //读取文件部分内容
    def reader = file.withReader { reader ->
        char[] buffer = new char[100]
        reader.read(buffer)
        return buffer
    }
    println reader
    
    def result = copy('../../GroovySpecification.iml'
           , '../../GroovySpecification2.iml')
    println result
    
    def copy(String sourcePath, String destationPath) {
        try {
            //首先创建目标文件
            def desFile = new File(destationPath)
            if (!desFile.exists()) {
                desFile.createNewFile()
            }
    
            //开始copy
            new File(sourcePath).withReader { reader ->
                def lines = reader.readLines()
                desFile.withWriter { writer ->
                    lines.each { line ->
                        writer.append(line + "\r\n")
                    }
                }
            }
            return true
        } catch (Exception e) {
            e.printStackTrace()
        }
        return false
    }
    
    def person = new Person(name: 'Qndroid', age: 26)
    saveObject(person, '../../person.bin')
    
    def result = (Person) readObject('../../person.bin')
    println "the name is ${result.name} and the age is ${result.age}"
    
    def saveObject(Object object, String path) {
        try {
            //首先创建目标文件
            def desFile = new File(path)
            if (!desFile.exists()) {
                desFile.createNewFile()
            }
            desFile.withObjectOutputStream { out ->
                out.writeObject(object)
            }
            return true
        } catch (Exception e) {
        }
        return false
    }
    
    def readObject(String path) {
        def obj = null
        try {
            def file = new File(path)
            if (file == null || !file.exists()) return null
            //从文件中读取对象
            file.withObjectInputStream { input ->
                obj = input.readObject()
            }
        } catch (Exception e) {
    
        }
        return obj
    }
    

    9 json 和 xml 操作

    json:

    
    import groovy.json.JsonOutput
    import groovy.json.JsonSlurper
    
    class Person {
      String name
      int age
    }
    
    def list = [new Person(name: 'John', age: 25), new Person(name: 'Major', age: 26)]
    
    //对象 -> json字符串
    def json = JsonOutput.toJson(list) 
    println JsonOutput.prettyPrint(json) //格式化输出
    
    //json字符串 -> 对象
    def jsonslpuer = new JsonSlurper()
    jsonSlpuer.parse(json)
    

    xml:

    final String xml = '''
        <response version-api="2.0">
            <value>
                <books id="1" classification="android">
                    <book available="20" id="1">
                        <title>疯狂Android讲义</title>
                        <author id="1">李刚</author>
                    </book>
                    <book available="14" id="2">
                       <title>第一行代码</title>
                       <author id="2">郭林</author>
                   </book>
                   <book available="13" id="3">
                       <title>Android开发艺术探索</title>
                       <author id="3">任玉刚</author>
                   </book>
                   <book available="5" id="4">
                       <title>Android源码设计模式</title>
                       <author id="4">何红辉</author>
                   </book>
               </books>
               <books id="2" classification="web">
                   <book available="10" id="1">
                       <title>Vue从入门到精通</title>
                       <author id="4">李刚</author>
                   </book>
               </books>
           </value>
        </response>
    '''
    
    def xmlSluper = new XmlSlurper()
    def response = xmlSluper.parseText(xml)
    
    println response.value.books[0].book[0].title.text()  //疯狂Android讲义
    println response.value.books[0].book[0].@avuilable   //查看属性
    
    //xml 查找操作
    response.value.books.each { books ->
      books.book.each { book ->
          def author = book.author.text()
          if(author.equals('李刚')) {
            list.add(book.title.text())
          }
      }  
    }
    println list.toListString()
    
    //深度遍历
    response.depthFirst.findAll { book ->
        return book.author.text() == '李刚'
    }
    
    //广度遍历
    response.value.books.children().findAll { node ->
        node.name() == 'book' && node@id == '2'
    }.collect {
        return node.title.text()
    }
    
    
    /**
     * 生成xml格式数据
     * <langs type='current' count='3' mainstream='true'>
     * <language flavor='static' version='1.5'>Java</language>
     * <language flavor='dynamic' version='1.6.0'>Groovy</language>
     * <language flavor='dynamic' version='1.9'>JavaScript</language>
     * </langs>
     */
    def sw = new StringWriter()
    def xmlBuilder = new MarkupBuilder(sw) //用来生成xml数据的核心类
    //根结点langs创建成功
    xmlBuilder.langs(type: 'current', count: '3',mainstream: 'true') {
       //第一个language结点
       language(flavor: 'static', version: '1.5') {
           age('16')
       }
       language(flavor: 'dynamic', version: '1.6') {
           age('10')
       }
       language(flavor: 'dynamic', version: '1.9', 'JavaScript')
    }
    println sw
    
    def langs = new Langs()
    xmlBuilder.langs(type: langs.type, count: langs.count,
            mainstream: langs.mainstream) {
        //遍历所有的子结点
        langs.languages.each { lang ->
            language(flavor: lang.flavor,
                    version: lang.version, lang.value)
        }
    }
    println sw
    //对应xml中的langs结点
    class Langs {
        String type = 'current'
        int count = 3
        boolean mainstream = true
        def languages = [
                new Language(flavor: 'static',
                        version: '1.5', value: 'Java'),
                new Language(flavor: 'dynamic',
                        version: '1.3', value: 'Groovy'),
                new Language(flavor: 'dynamic',
                        version: '1.6', value: 'JavaScript')
        ]
    }
    //对应xml中的languang结点
    class Language {
        String flavor
        String version
        String value
    }
    

    10 面向对象

    面向对象方面主要是注意几个和 java 的区别点:

    • groovy 中的类及成员变量默认类型都是 public 的
    • groovy 特有的 trait 接口,tarit 接口中可以有方法实现
    • groovy 中可以调用未定义的方法
    /**
     * 定义类
     * 默认都是 public
     */
    class Person implements Action {
        String name
        int age
    
        def increateAge(Integer years) {
            this.name += years
        }
    
        @Override
        String toString() {
           return "the name is ${name}, the age is ${age}"
        }
    
        @Override
        void eat() {
    
        }
    
        @Override
        void drink() {
    
        }
    
        @Override
        void play() {
    
        }
    }
    
    /**
     * 接口定义
     */
    interface Action {
        void eat()
        void drink()
        void play()
    }
    
    /**
     * trait 有方法实现的接口
     */
    trait DefaultAction {
        abstract void eat()
        void play() {
            println 'i can play'
        }
    }
    
    def person = new Person(name: 'Android', age: 26)
    println person
    
    

    调用未定义的方法主要通过下面几个途径实现:

    • methodMissing 方法
    • invokeMethod 方法
    • metaClass 注入方法和属性(类似 kotlin 的扩展属性,扩展方法)
    /**
     * 定义类
     * 默认都是 public
     */
    class Person  {
        String name
        int age
    
        def increateAge(Integer years) {
            this.name += years
        }
    
        /**
         * 当调用的方法不存在的时候会调用这个方法
         */
        def methodMissing(String name, Object args) {
            return "methodMissing the method is ${name}, the params is ${args}"
        }
    
        /**
         * 当调用的方法不存在的时候会调用这个方法,
         * 如果定义了 methodMissing 就不会调用 invokeMethod
         * @param name the name of the method to call
         * @param args the arguments to use for the method call
         * @return
         */
        def invokeMethod(String name, Object args) {
           return "invokeMethod the method is ${name}, the params is ${args}"
        }
    }
    
    
    def person = new Person(name: 'Android', age: 26)
    println person.cry()
    
    /**
     * 注入属性
     */
    Person.metaClass.sex = 'male'
    def person2 = new Person(name: 'Android', age: 26)
    println(person2.sex)
    
    person2.sex = 'famale'
    println(person2.sex)
    
    /**
     * 注入方法
     */
    Person.metaClass.sexUpperCase = { ->
        sex.toUpperCase()
    }
    
    def person3 = new Person(name: 'Android', age: 26)
    println person3.sexUpperCase()
    
    //注入静态方法
    Person.metaClass.static.createPerson = { String name, int age ->
        new Person(name: name, age: age)
    }
    
    def person4 = Person.createPerson("hello", 10)
    println(person4.name + ": " + person4.age)
    
    

    相关文章

      网友评论

          本文标题:gradle7 从上手到实践之 groovy 基础语法

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