Gradle实战-04-Gradle核心语法讲解与实战

一、本章概述

  1. groovy基础语法、变量、字符串
  2. groovy闭包讲解 比Java,Javascript的闭包更灵活
  3. groovy数据结构
  4. groovy面向对象

二、基础语法

一、变量

1. 变量的类型 1.int double 等基本类型 2. 对象类型--> 最终都是对象类型

package variable

int x = 10
println x.class

double y = 3.14
println y.class

输出:

class java.lang.Integer
class java.lang.Double

Process finished with exit code 0

2. 变量的定义

1. 强类型定义 2. 弱类型定义(def 定义)

强类型定义就是指明了具体的数据类型,而弱类型定义就是不指明数据类型,而是通过数据推断出来具体的数据类型。

def x_1 = 11
println x_1.class
def y_1 = 3.14
def name = 'android'
x_1 = 'iOS'
println x_1.class
println y_1.class
println name.class

输出:

class java.lang.Integer
class java.lang.String
class java.math.BigDecimal
class java.lang.String

从上面可以看出,def定义的变量是可以随意改变数据类型的。 

注意:如果是自己用就可以用 def,如果是用于提供给其他模块使用,则需要强类型的定义

二、字符串

1. 字符串有两种定义方式  String 和 GString 这两种类型,GString 可扩展字符串 ${name}

name = 'android'
//x_1 = 'iOS'
//println x_1.class
//println y_1.class
//println name.class

//1. 单引号字符串和Java中双引号字符串
def name = 'a single string'
println name.class

def thupleName = '''\
line one
line two
line three
'''
println thupleName
println thupleName.class

//单引号 和 三引号 定义的字符串的区别
//三个单引号可以直接指定格式
//如果是单引号则需要拼接和转移字符才能实现该功能

def doubleName = "this a common String"
println doubleName.class

//双引号与其他有什么区别
//可扩展字符串
//有了扩展表达式 ${变量名},则就是可扩展字符串
def name_android = "Qndroid"
def sayHello = "hello: ${name_android}"
println sayHello
//class org.codehaus.groovy.runtime.GStringImpl
println sayHello.class

//可扩展可以做任意的表达式
def sum = "The sum of 2 and 3 equals ${2+3}"
println sum

def result = echo(sum)
//结果表明String类型和GString是可以相互转化的
println result
println result.class

String echo(String message){
    return message
}

2. 新增操作符

///字符串的方法
//1. java.lang.String 来源
//2. DefaultGroovyMethods
//3. StringGroovyMethods 1. 普通类型的参数 2. 闭包类型的参数

//普通类型参数
def str = "Hello groovy"
//center左右字符串的填充 agroovya
println str.center(8, 'a')

//添加已有字符串的左边 aagroovy
println str.padLeft(8, 'a')

//方法比较
def str2 = 'Hello'
//1. 方法比较
//println str.compareTo(str2)
//2. 操作符比较
println str > str2

//获取指定位置字符
println str.getAt(0)
println str[0]
//输出的是gr,左右是闭区间
println str[0..1]


//str中减去str2字符串
println str.minus(str2)
//倒序输出
println str2.reverse()
//首字母大写
println str.capitalize()
//判断是否是数字类型
println str.isNumber()

3. 逻辑控制

//Groovy中的switch比Java中更强大
//Java中只能指定一种类型,不会匹配到多种类型
def x = 1.23
def result
switch (x.class) { //可以解决 instanceof if else这种 直接进行类型判断
    case 'foo':
        resutl = 'found foo'
        break
    case 'bar':
        result = 'found bar'
        break
    case [4,5,6, 'inlist']://列表
        result = 'list'
        break
    case 12..30:
        result = 'range'//范围
        break
    case Integer:
        result = 'integer'
        break
    case BigDecimal:
        result = 'bigDecimal'
        break
    default:
        result='default'
}

println result

//对范围的for循环
def sum = 0
for (i in 0..9){
     sum +=i
}

//println sum
sum = 0

//对List的循环
for (i in [1,2,3,4,5,6,7,8,9]){
    sum+=i
}

//对Map的循环
for (i in ['lili':1, 'lucy':2,'xiaoming':3]){
    sum+=i.value
}

三、闭包

1. Groovy闭包的概念 2. Groovy闭包的使用详解

Groovy中闭包比其他语言中的闭包更加强大

闭包概念:

1. 闭包就是一个代码块,和方法差不多 2. 闭包的调用,使用call或者方法的调用方法进行调用

package variable

def closure = { // 这样已经算作是一个闭包
    println 'Hello groovy'
}

closure.call()
//注意和方法的调用比较
closure()

//输出
Hello groovy
Hello groovy

2. 闭包参数 闭包如何传递参数

def closure = { String name, int age ->
    println "Hello ${name}, My age is ${age}"
}

def name = 'groovy'
closure.call('groovy',10)
closure(name,4 )

//输出
Hello groovy, My age is 10
Hello groovy, My age is 4

3. 闭包只有一个传入参数,可以省略参数列表,该参数使用 it 代替

def closurer = {
    println "Hello ${it}" // it 是默认的参数,只有一个参数的使用
}

closurer("ShangHai")

//输出
Hello ShangHai

4. 闭包返回值 闭包一定有返回值,默认是闭包的最后一行

//闭包返回值 闭包一定有返回值
def returnClosure = { String na->
    //return "Hello ${na}" //有返回值
    "Hello ${na}" //也有返回值
}
def result = returnClosure("BeiJing")
println result

//输出
Hello BeiJing

注意:插件也是用的Groovy语言开发的

5. 闭包结合方法使用

//闭包的使用
//用指定方法来求阶乘
int x = fab(5)
println x
int y = fab2(5)
println y

int z = cal(101)
println z

//upto 
int fab(int number){
    int result = 1
    1.upto(number, {num -> result*=num})
    return result
}

//downto
int fab2(int number){
    int result = 1
    number.downto(1){
        num -> result*=num
    }
    return result
}

//累加
int cal(int number){
    int result
    number.times {
        num -> result+= num
    }
    return result
}

6. 闭包和字符串结合使用

//字符串与闭包的结合使用
String str = 'the 2 and 3 is 5'

//each遍历
//如果闭包在方法参数的最后位置,则可以将闭包放在方法括号外部
//each返回值是str本身
str.each {
    //输出字符串中的每个字符  
    String temp -> println temp
}

//find来查找符合条件的第一个字符
//输出打印 2 
println str.find {
   String s -> s.isNumber()
}

//查找所有符合条件的对象并返回集合
//输出打印[2, 3, 5]
def list = str.findAll {
    String s -> s.isNumber()
}

//[2, 3, 5]
println list.toListString()

//只要符合条件就返回true 否则返回false
def result = str.any {
    String s -> s.isNumber()
}

println result

//判断是否每一项都符合条件,如果都符合条件返回true,否则返回false
def result2 = str.every {
    String s -> s.isNumber()
}

println result2

//所有经过闭包变换处理的对象都放在一个新的集合中
def list2  = str.collect {
    it -> it.toUpperCase()
}
//[T, H, E,  , 2,  , A, N, D,  , 3,  , I, S,  , 5]
println list2.toListString()

7. 闭包进阶  

闭包进阶的三个变量 this,owner,delegate 

//1. 闭包的三个关键变量 this owner delegate 闭包强大的核心
def scriptClosure = {
    println "scriptClosure this: "+this //this 代表闭包定义处的类
    println "scriptClosure owner: "+owner //代表闭包定义处的类或者对象
    println "scriptClosure delegate: "+delegate //代表任意对象,有默认值为owner
}

scriptClosure.call()

//输出
scriptClosure this: variable.closure03@531f4093
scriptClosure owner: variable.closure03@531f4093
scriptClosure delegate: variable.closure03@531f4093

 this,owner,delegate 三种变量的区别

//相当于定义个了一个内部类,其外部类是closure03
class Person {

    //def static classClosure  = {
    def classClosure  = {
        println "classClosure this: "+this //this 代表闭包定义处的类
        println "classClosure owner: "+owner //代表闭包定义处的类或者对象
        println "classClosure delegate: "+delegate //代表任意对象,有默认值为owner
    }

    def say(){
        def classClosure  = {
            println "methodClassClosure this: "+this //this 代表闭包定义处的类
            println "methodClassClosure owner: "+owner //代表闭包定义处的类或者对象
            println "methodClassClosure delegate: "+delegate //代表任意对象,有默认值为owner
        }
        classClosure.call()
    }
}
Person p = new Person()
p.classClosure.call()
p.say()


//在闭包中定义一个闭包,看this和owner是否还是有区别?
def nestClosure = {
    def innerClosure = {
        println "innerClosure this: "+this //this 代表闭包定义处的类,指向closure03这个类??
        println "innerClosure owner: "+owner //代表闭包定义处的类或者对象 可以指向闭包对象 指向nestClosure ?
        println "innerClosure delegate: "+delegate //代表任意对象,有默认值为owner
    }
    innerClosure.delegate = p //修改默认的delegate对象,如果不修改,则delegate和owner指向的都是同一个对象
    innerClosure.call()
}
nestClosure.call()

//总结:如果是在类中定义闭包,则this, owner, delegate 是一样的
//但是如果在闭包中嵌套闭包,则this 和 owner, delegate 不一样,owner指向最近的闭包对象
//如果人为的修改闭包的delegate, 则delegate则和owner不一样
//this和owner是不能修改的


//输出
classClosure this: variable.Person@134d26af
classClosure owner: variable.Person@134d26af
classClosure delegate: variable.Person@134d26af
methodClassClosure this: variable.Person@134d26af
methodClassClosure owner: variable.Person@134d26af
methodClassClosure delegate: variable.Person@134d26af
innerClosure this: variable.closure03@6187d1f5
innerClosure owner: variable.closure03$_run_closure1@17aad511
innerClosure delegate: variable.Person@134d26af

闭包委托策略 

//2. 闭包委托策略
//闭包的this, owner,delegate 的作用是什么?
class Student {
    String  name
    int age = 10
    def pretty = {
        //此处的name是指向定义闭包处的类(Student类)的name
        "My name is ${name} age is ${age}"
    }

    String toString() {
        pretty.call()
    }
}

class Teacher {
   String name
}

def stu = new Student(name: 'Sarah')
def tea = new Teacher(name: 'Jack')
println stu.toString()
stu.pretty.delegate = tea
//stu.pretty.resolveStrategy = Closure.OWNER_FIRST //代理策略 Owner优先
//stu.pretty.resolveStrategy = Closure.OWNER_FIRST
stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST //代理策略 代理优先
//stu.pretty.resolveStrategy = Closure.DELEGATE_ONLY //代理策略 只有代理
println stu.toString()
//如何在不修改stu的name的情况下将输出名称修改为老师的名称?

//代理以及策略是在写框架的时候会用到,其他情况下很少用


//输出
My name is Sarah age is 10
My name is Jack age is 10

注意理解相关的概念和使用方法,也就是其中的技巧。

四、数据结构

1. 列表的定义

//def list = new ArrayList() //Java中的定义方式
def list = [1,2,3,4,5]
println list.class  //class java.util.ArrayList
println list.size() //5

def array = [1, 2, 3, 4, 5,] as int[] // int[] 数组
int[] array2 = [1, 2, 3, 4, 5] //数组

2. 列表添加元素

//方法一:列表的添加元素
list.add(6)
println list.toListString() //1 2 3 4 5 6
//方法二:列表添加元素
list.leftShift(7)
//方法三:列表添加元素
list<<8
println list.toListString()
//方法四:列表添加元素
def plusList = list + 9;
println plusList

3. 列表删除元素

//list的删除操作
list.remove(7)
println list.toListString()
//移除最后一个元素
list.removeLast()
println list.toListString()
//移除符合条件的元素,比如被2整除 [1, 3, 5]
list.removeIf{it ->  it%2==0 }
println list.toListString()

4. 列表排序

//列表排序
def sortList = [6, -3, 9, 2, -7, 10]
//按照绝对值的大小进行排序
//Comparator mc  = {a, b -> a==b ? 0: Math.abs(a)< Math.abs(b)? -1: 1}
//Collections.sort(sortList, mc)
sortList.sort{ a, b -> Math.abs(a)< Math.abs(b)? 1: -1}
println sortList

//按照某种规则进行指定规则排序
def sortStringList = ['a', 'bc','hello','kotlin', 'groovy', 'java']
sortStringList.sort{it-> it.size()}
println sortStringList

5. 列表查找元素

//列表中的查找
def findList = [-3, 9, 6, 2, 7, 1, 5]
//查找第一个符合条件的元素
int result = findList.find { return it%2==0 }
println result
//查找所有符合条件的元素
def resultList = findList.findAll {return it%2==0}
//[6, 2]
println resultList.toListString()
//查找是否有元素是否不能被2整除
def resultAny = findList.any {return it%2!=0}
println resultAny
//是否所有的元素都能整除2
def resultEvery = findList.every { return it%2==0}
println resultEvery

6. 列表中查找最大最小值

//查找列表中的最小值
def min = findList.min()
println min
//查找列表中对最大值
def max = findList.max()
println max

//按照规则选中最小的值
def minNew = findList.min { return Math.abs(it)}
println minNew

7. 统计列表中符合条件的元素个数

//count 用于统计符合规则的元素个数
def num  = findList.count { return it%2== 0}
println num

8. Groovy中的映射

//groovy中的映射
def map = new HashMap()
def colors = [red:'ff0000', green:'00ff00', blue: '0000ff']
def red =  colors['red']
println red

println colors.red

9. Map映射添加元素

//添加元素 比较常用
colors.yellow = 'ffff00'
//同样是添加元素,put方法不常用
colors.put('purple', 'ff00ff')
println colors.toMapString()

colors.complex = [a: 1, b:2]
println colors.toMapString()

//class java.util.LinkedHashMap
println colors.getClass()

10. Map的遍历

def students = [
        1:[number:'0001', name:'bob', score: 55, sex: 'male'],
        2:[number:'0002', name:'Johnny', score: 60, sex: 'female'],
        3:[number:'0003', name:'Clarie', score: 67, sex: 'female'],
        4:[number:'0004', name:'Amy', score: 80, sex: 'male'],
]

遍历
students.each {
    def student ->
        println "the key is ${student.key}, the value is ${student.value}"
}

students.eachWithIndex{ def student, int index ->
    println "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}"
}

11. Map 映射查找

//Map的查找
def entry = students.find {
    def student ->  return student.value.score >= 60
}

println entry

def entrys = students.findAll {
    def student -> return student.value.score>60
}
println entrys

def count = students.count {
    def student -> return student.value.score>=60 && student.value.sex=='male'
}

println count

//查找所有及格的学生
def names = students.findAll {
    def student -> return student.value.score>=60
}.collect {//重新构造一个列表
    return it.value.name
}
//打印输出一个列表
println names.toListString()

12. Map 映射分组

//分组 按照某个标签分组
def groups = students.groupBy {
    def student -> return student.value.score>=60?"及格":"不及格"
}
//[不及格:[1:[number:0001, name:bob, score:55, sex:male]],
//及格:[2:[number:0002, name:Johnny, score:60, sex:female],
//3:[number:0003, name:Clarie, score:67, sex:female], 4:[number:0004, name:Amy, score:80, sex:male]]]
println groups.toMapString()

13. Map的排序

//排序
def sort = students.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()

14. 范围的定义

def range = 1..10
println range[0] //1
println range.contains(10) //true

//range的起始值 有两个属性 from,to
println range.from
println range.to

15. 范围range的遍历

//遍历
range.each {
    println it
}

for (i in range){
    println i
}

16. 范围range在方法中的使用

def result = getGrade(78)
println result //良好

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
   }
   return result
}

五、面向对象

1. Groovy中类,接口等的定义和使用和Java一致

2. Groovy中的元编程Java中没有,这是Groovy比Java强大的地方

1. 接口定义

//Action.groovy
//groovy 中不允许创建非public类型的方法
interface Action {

    void eat()

    void drink()

    void play()
}

2. 类定义

//Person.groovy
//1. groovy中默认的都是public类型的,都会省略public修饰符
class Person implements Action, Serializable{

    String name

    Integer age

    def increaseAge(Integer years){
        this.age += years
    }

    @Override
    void eat() {

    }

    @Override
    void drink() {

    }

    @Override
    void play() {

    }

    //methodMissing如果和invokeMethod同时存在的情况下,会走methodMissing方法
    def methodMissing(String name, Object args){
        return "the method ${name} is missing"
    }

    //在对象调用一个方法在找不到的情况下,调用它代替,可以避免抛出异常
    def invokeMethod(String name, Object args){
        return "the method is ${name}, the params is ${args}"
    }

}

其中 methodMissing 和 invokeMethod 方法是两个比较特殊的方法,可以在对象调用一个不存在的方法的时候避免抛出异常,并按照优先级调用两个方法中的其中一个。同时需要注意,groovy语法中默认都是public修饰的,不需要添加public 关键字。

//2. 无论你是直接. 还是调用get/set最终都是调用 get/set方法
def person = new Person(name: 'Lucky', age: 26)
println "the name is ${person.name}, the age is ${person.age}"

person.increaseAge(10)
println person.age

//因为在Person中定义了invokeMethod和MethodMissing方法,所以不会报错
println person.cry() 
//又像接口 又像抽象类,实现是用implements
trait DefaultAction {

    abstract void eat()

    void play(){
        println 'i can not  play'
    }
}

六、元编程

如上便是调用方法的过程,有好多分支判断,关于 invokeMethod 和 MethodMissing 前面已经介绍过了,而MetaClass是本节要介绍的元编程相关的内容。

1. MetaClass 非常强大,可以为类动态的添加属性和方法,如下:

//script.groovy
//methodClass强大
//为类动态的添加一个属性 sex属性
Person.metaClass.sex = 'male'
def personNew = new Person(name:'', age: 10)
println personNew.sex

personNew.sex = 'female'
println "the new sex is : ${personNew.sex}"

//为类动态的添加方法
Person.metaClass.sexUpperCase = {-> sex.toUpperCase()}
def person2 = new Person(name:'lisi', age: 10)
println person2.sexUpperCase()

//为类动态的添加静态方法 createPerson静态方法
Person.metaClass.static.createPerson = {
    String name, int age-> new Person(name: name, age: age)}

def person3 = Person.createPerson('lisisi', 23)
println "the name is $person3.name and age is $person3.age"

感觉有点类似Kotlin和Flutter中的扩展方法,可以在不修改源码的情况下,动态添加方法。

2. 在不修改源码的情况下,为类添加方法

//ApplicationManager.groovy
package oop

class ApplicationManager {

    static void init(){
       ExpandoMetaClass.enableGlobally()
       //为第三方类添加方法 解决无法修改源码的问题
       Person.metaClass.static.createPerson = {String name, int age->
           new Person(name:name, age: age)
       }
       String.metaClass.static.printlog = {String data ->
           println data
       }
       String.metaClass.static.reversedata = {String data ->
           return data.reverse()
       }
    }
}
package oop

class PersonManager {

    static Person createPerson(String name, int age){
        //利用动态添加的createPerson静态方法创建Person对象 
        return Person.createPerson(name, age)
    }
}
package oop

class Entry {

    //应用程序入口
    static void main(def args){
        println "应用程序正在启动..."
        //初始化
        ApplicationManager.init()
        println '应用程序初始化完成...'
        def person = PersonManager.createPerson('wangwu',10)
        println "the person name is $person.name and age is $person.age"
        def student = 'studentxx'
        student.printlog("ddd")
        def result = student.reversedata("hello")
        println result
    }

}

三、总结 

如上总结了groovy中的变量、类、列表、映射等常见的数据类型,也介绍了常见的API操作,比如字符串操作、列表操作等,另外还有闭包的概念、使用以及this、Owner、delegate 等关键字的使用场景介绍,最后介绍了元编程的概念和使用,使得类可以动态的扩展属性和方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值