Gradle_01 groovy基础语法

684 阅读8分钟

github 代码在此

介绍部分

.1主流的构建工具

  • Ant(Apache Ant)
    软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于java环境中的软件开发
  • Maven
    从ant中借用了绝大多数构建任务,其突出的是依赖管理和项目发布
  • Gradle
    使用Groovy语言,构建脚本,不再像Maven一样使用xml

.2 Gradle介绍

一个开源的项目自动化构建工具,建立在Apache Ant和Apache Maven概念的基础上,并引入了基于Groovy的特定领域语言(DSL),而不再使用XML形式管理构建脚本。

.2.1 DSL(Domain Specific Language)

定义:针对某一领域,具有首先表达性的一种计算机程序设计语言。只针对一个领域做出来的简洁语言,而非为了通用设计。(MATLAB计算语言,UML建模语言,HTML浏览器可识别网页语言),Groovy主要用于做脚本。

1 Groovy语法

  • Groovy是基于java虚拟机的一种敏捷的动态语言,它是一种成熟的OOP(面向对象)编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同事又具有闭包和动态语言中的其他特性。
  • 结合了python、Ruby和SmallTalk的许多强大的特性
  • groovy可以与java完美结合,可以使用已经存在的所有java类库
  • 语法上支持动态类型,闭包等新一代语言特性
  • 既支持面向对象编程也支持面向过程编程
  • 既可以作为编程语言也可以作为脚本语言
  • 没有访问权限控制,都是public的

1.1 变量

//不管声明基本类型还是对象类型,groovy所有类型都是对象类型
int x = 10;
println x.class //class java.lang.Integer
double y =3.14
println y.class //class java.lang.Double

1.1.1 def关键字的是用

//def 弱类型定义
//如果变量不会被外部使用,使用def声明,如果要被外部使用,定义为java方式强类型
def x_1 = 11
println(x_1.class)//class java.lang.Integer
def y_1 = 3.1415
println(y_1.class)//class java.math.BigDecimal
def name = "Android"
println(name.class)//class java.lang.String

// 使用def定义的类型是可变类型的,动态类型
x_1 = 'Test'
println(x_1.class)//class java.lang.String

1.1.2 字符串

①定义方式
//一个单引号,无格式字符串,需要字符串拼接,转义字符等指定格式
def name = 'a single string'
println name.class //class java.lang.String

//三个单引号
def thupleName = '''three single string'''
println thupleName.class //class java.lang.String

//三个单引号,直接指定格式,无需 + "" 拼接
def thupleName2 = '''line one
line two
line three
'''
println thupleName2

//双引号定义字符串   可扩展字符串
def doubleName = "this is a common String"
println(doubleName.class)//class java.lang.String
def name2 = "Android"
//如果是可扩展字符串,类型变为GString
def sayHello = "Hello:${name2}"
println( sayHello )//Hello:Android
println( sayHello.class ) // class org.codehaus.groovy.runtime.GStringImpl

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

//传入了GString   接收参数为String,无需像java一样转型
def result = echo(sum)
println(result)//class java.lang.String
println(result.class)//class java.lang.String
String echo(String messagse){
    return messagse
}
②字符串方法
  • java.lang.String的方法
  • DefaultGroovyMethods
  • StringGroovyMethods (继承于DefaultGroovyMethods),包括普通类型的参数和闭包类型的参数
def str = "groovy"
//填充
//center() 对字符串的填充
println(str.center(8,'a'))//agroovya 两边填充a
println str.padLeft(8,'a')//aagroovy  左边填充a
println str.padRight(8,'a')//groovyaa  右边填充a
//比较
def str2 = "Hello"
println str > str2//unicode 编码比较 true
//索引
println str[0]//g
println str[0..1]//gr
//减法
def str3 = "Hello groovy"
println str3.minus(str2)//groovy
//等同于'-'操作符
println str3 - str2
//逆向操作
println  str.reverse()
//首字母大写
println str.capitalize()
//判断是否是数字类型的字符串
println str.isNumber()
//转化类型
def strBoolean = '1'
println strBoolean.toBoolean()//true
def strLong = '1'
println strLong.isLong()
strLong.toLong()
def strDouble = '1'
println strDouble.isDouble()
strDouble.toDouble()

1.1.3 逻辑控制

  • 顺序逻辑:单步往下执行
  • 条件逻辑if else ,switch case
  • 循环逻辑 while循环,for循环
//groovy 中的switch case 可以是任何类型
def x = 1.23
def result
//switch (x){
switch (x.class){
    case 'foo':
        result = 'found foo'
        break
    case 'bar':
        result = 'bar'
        break
    case [4,5,6,'inlist']://列表
        result = 'list'
        break
    case 12..30://范围
        result = 'range'
        break
    case Integer:
        result = 'integer'
        break
    case BigDecimal:
        result = 'big decimal'
        break
    default:result = 'default'
}
println result//big decimal

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

//对list 的循环
for (i in [1,2,3,4,5,6,7,8,9]){
    sum += i
}
//对map的循环
for (i in ['lili':1,'luck':2,'xiaoming':2]){
    sum += i.value
}

2 闭包

2.1闭包与基本类型的使用

//闭包参数
def clouser = { String name ,int age->
    println "Hello ${name},age is ${age}"
}
//clouser.call()//hello null
clouser("groovy",29)//Hello groovy,age is 29

//每一个闭包都有一个默认参数it
def clouser2 = {
    println "2 Hello ${it}"
}
clouser2('Groovy')//2 Hello Groovy

//方法返回值
def clouser3 = { String name ->
    return  "3 Hello ${name}"
}
println clouser3('groovy')//3 Hello groovy

//也是有返回值的 返回null
def clouser4 = { String name ->
    println  "4 Hello ${name}"
}
println clouser4('groovy')//null 

2.2 闭包的一些基础算法

int x = fab(5);
println x
//求指定number的阶乘
int fab(int number){
    int result = 1
    1.upto(number,{num -> result *= num})
    return result
}

int fab2(int number){
    int result = 1
//    number.downto(1,{num -> result *= num})
    //闭包放在括号内和括号外的效果是一致的
    number.downto(1){
         num -> result *= num
    }
    result result;
}

int y = cal(101)
println y
//求和 1到100
int cal(int number){
    int result = 0;
    number.times{
        num ->result += num
    }
    return result
}

2.3 闭包与字符串

String str = 'the 2 and  3 is 5'
//1 each 遍历
str.each {
    //每个字符串增加一倍
    String temp -> print temp.multiply(2)//tthhee  22  aanndd  tthhee  33  iiss  55
}
println ''
//2 find 查找符合条件的第一个
def findstr = str.find{
    String s -> s.isNumber()
}
println findstr//2
//3 findAll 查找符合条件的集合
def list = str.findAll{
    String s -> s.isNumber()
}
println list.toListString()//[2, 3, 5]
//4 判断字符串中是否包含数字
def result = str.any{
    String s -> s.isNumber()
}
println result//true
//5 判断是否string中每一位都是数字
println str.every {String s -> s.isNumber()}//false
//6 输出字符串转大写的字符串集合
def upList = str.collect{
    it.toUpperCase()
}
println upList//[T, H, E,  , 2,  , A, N, D,  , T, H, E,  , 3,  , I, S,  , 5]

2.4 闭包进阶

/**
 * 闭包的三个重要变量: this,owner,delegate
 */
def scriptClosure= {
    //this 代表闭包定义处的类
    println "scriptClosure this:"+this//scriptClosure this:closureadvance.clousure1@d5b810e
    //代表闭包定义处的类或者对象
    println "scriptClosure owner:"+owner//scriptClosure owner:closureadvance.clousure1@d5b810e
    //代表任意对象,默认值与owner一直
    println "scriptClosure delegate:"+delegate//scriptClosure delegate:closureadvance.clousure1@d5b810e
}
scriptClosure.call()
println '-------------------'
//定义了一个内部类
class Person{
    def static classClosure = {
        println "classClosure this:"+this//
        println "classClosure owner:"+owner
        println "classClosure delegate:"+delegate//
    }

    def static say(){
        def  classClosure = {
            println "method classClosure this:"+this
            println "method classClosure owner:"+owner
            println "method classClosure delegate:"+delegate//
        }
        classClosure.call()
    }
}
Person.classClosure.call()//classClosure this/owner/delegate:class closureadvance.Person
Person.say()//method classClosure this/owner/delegat:class closureadvance.Person
//去掉static
//Person p = new Person();
//p.classClosure.call()//classClosure this:closureadvance.Person@4dbb42b7,指向了具体实例对象
//p.say()//method classClosure this:closureadvance.Person@4dbb42b7,指向了具体实例对象

println '-------------------'
//闭包中定义一个闭包
def nestClosure = {
    def innerClosure = {
        //这里的this表示clousure1的实例对象
        println "innerClosure this:"+this//classClosure this:closureadvance.clousure1@7c711375
        //在类中或者方法中定义闭包 ,this,owner.delegate是一致的,但是在闭包中定义闭包,那么三者值将不再一致,owner和delegate一致
        println "innerClosure owner:"+owner//classClosure owner:closureadvance.clousure1$_run_closure2@48aca48b
        println "innerClosure delegate:"+delegate//classClosure delegate:closureadvance.clousure1$_run_closure2@48aca48b
    }
    Person p = new Person();
    innerClosure.delegate = p//人为修改默认的delegate对象,输出innerClosure delegate:closureadvance.Person@272113c4,delegate和owner不再一致
    innerClosure.call()
}
nestClosure.call()

闭包的委托策略

class Student{
    String name
    def pretty = {"My name is ${name}"}
    String toString(){
        pretty.call()
    }
}

class Teacher{
    String name
}

def stu = new Student(name:'Sarash')
def tea = new Teacher(name:'Android')
println stu.toString()//my name is Sarash
stu.pretty.delegate = tea
println stu.toString()//my name is Sarash
//指定resolveStrategy为DELEGATE_FIRST,从delegate对象优先寻找属性和方法
stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST
println stu.toString()//My name is Android

3 数据结构

3.1 列表

数组和list的定义

//def list = new ArrayList()//java定义方式
//定义list
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[] array2 = [1,2,3,4,5]

列表的增加删除

/**
 * list的添加元素
 */
list.add(6)
list.leftShift(7)
println list.toListString()//[1, 2, 3, 4, 5, 6, 7]
list << 8
println list.toListString()//[1, 2, 3, 4, 5, 6, 7, 8]
def plusList = list+9
println plusList.toListString()//[1, 2, 3, 4, 5, 6, 7, 8, 9]
println '------------------------'
/**
 * list的删除元素
 */
//list.remove(7)//移除第八个元素后的元素
//println list.toListString()//[1, 2, 3, 4, 5, 6, 7]
//list.remove((Object)7)//移除元素7
//println list.toListString()//[1, 2, 3, 4, 5, 6]
list.removeAt(7)//移除第八个元素后的元素
println list.toListString()//[1, 2, 3, 4, 5, 6, 7]
list.removeElement(6)//移除元素6
println list.toListString()//[1, 2, 3, 4, 5, 7]
list.removeAll{return it%2 == 0}
println list.toListString()//[1, 3, 5, 7]
println list - [6,7]//[1, 3, 5]
println list.toListString()//[1, 3, 5, 7]

列表的排序

/**
 * 列表的排序
 */
def sortList = [6,-3,9,2,-7,1,5]
//两种java排序方法
//从小到大排序
Collections.sort(sortList)
println sortList//[-7, -3, 1, 2, 5, 6, 9]
//添加绝对值大小规则
Comparator mc = {a,b ->
    a == b?0:
            Math.abs(a)<Math.abs(b)?-1:1
}
Collections.sort(sortList,mc)
println sortList//[1, 2, -3, 5, 6, -7, 9]

//groovy排序
//列表排序
sortList.sort()
sortList.sort { a, b ->
    a == b ? 0
            : Math.abs(a)<Math.abs(b)?1:-1
}
println sortList//绝对值从大到小[9, -7, 6, 5, -3, 2, 1]
//字符串数组排序
def sortStringList = ['abc','z','hello','groovy','java']
sortStringList.sort{it -> return it.size() }
println sortStringList//根据字符串长度排序 [z, abc, java, hello, groovy]
//列表的查找
def findList = [6,-3,9,2,-7,1,5]
int result = findList.find {return  it%2 == 0}
println result//第一个偶数 6
def results = findList.findAll() {return  it%2 == 0}
println results.toListString()//所有偶数 [6, 2]
def any =findList.any{return it%2 !=0}
println any//是否存在奇数 true
def every = findList.every {return it%2 == 0}
println every//是否都是偶数 false
println findList.min()//最小值-7
println findList.max()//最大值9
println findList.min{return Math.abs(it)}//绝对值最小值1
println findList.max{return Math.abs(it)}//绝对值最大值9

列表的统计

//类似sql的统计
println findList.count{return it%2 !=0}//统计奇数个数

3.2 映射

//map定义
def colors = [red:'ff0000',
              gray:'00ff00',
              blue:'0000ff']
//索引方式
println colors['red']
println colors.red
//添加元素
colors.yellow = 'ffff00'
println colors.toMapString()//[red:ff0000, gray:00ff00, blue:0000ff, yellow:ffff00]
colors.leftShift(organe:'ff850d')
println colors
colors.complex = [a:1,b:2]//添加一个map进去,添加任意类型
println colors//[red:ff0000, gray:00ff00, blue:0000ff, yellow:ffff00, organe:ff850d, complex:[a:1, b:2]]
println colors.getClass()//class java.util.LinkedHashMap
//删除方法
colors.remove('red')
println colors
//修改方法
colors.gray = 'huise'
println colors//[gray:huise, blue:0000ff, yellow:ffff00, organe:ff850d, complex:[a:1, b:2]]

groovy中map的操作

  • 遍历
def students = [
        1:[number:'01',name:'Bob',score:55,sex:'male'],
        2:[number:'02',name:'Johnny',score:62,sex:'female'],
        3:[number:'03',name:'Claire',score:73,sex:'female'],
        4:[number:'03',name:'Amy',score:66,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}"
}
//直接遍历key,value值
students.each {key,value ->
    println "the key is ${key},"+
            "the value is ${value}"
}
println '-------------'
  • 查找
//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//1
//过滤 输出所有及格的人的名字
def names = students.findAll { def student ->
    student.value.score >= 60
}.collect {//过滤出名字
    return it.value.name
}
println names.toListString()//[Johnny, Claire, Amy]

//分组,将不及格和及格的人进行分组
def group = students.groupBy {
    def student ->
        return student.value.score >= 60 ? '及格':'不及格'
}
//[不及格:[1:[number:01, name:Bob, score:55, sex:male]],
// 及格:[2:[number:02, name:Johnny, score:62, sex:female], 3:[number:03, name:Claire, score:73, sex:female], 4:[number:03, name:Amy, score:66, sex:male]]]
println group.toMapString()
  • 排序
//将学生由分数从低到高排序
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()

3.3 范围

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 = "${number}分,不及格"
            break
        case 60..70:
            result = "${number}分,及格"
            break
        case 70..80:
            result = "${number}分,良好"
            break
        case 80..100 :
            result = "${number}分,优秀"
            break
    }
}
println getGrade(75)

4 面向对象

4.1 类和接口

class Person {
    String name
    Integer age
    def increaseAge(Integer years){
        this.name += years
    }
}

①无论是.调用还是set/get调用,实际都是调用了set/get

def person = new Person(name:'Android',age:29)
//.name 调用的事getName()方法
println "the name is ${person.name}"+
        "the age is ${person.age}"
person.increaseAge(2)

②接口,跟java的区别是不能用protected修饰

//接口不允许定义非public的方法
interface Action {
    void eat()
    void drink()
    void play()
}

③trait 接口和抽象类的结合

trait DefaultAction {
    abstract void eat()

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

4.2 运行时

4.2.1 invokeMethod和methodMissing

如果调用了一个Person中不存在的方法,编译时不会不通过,运行时会报错,需要重写invokeMethod或methodMissing方法,这样运行时也不会报错了,如果两个方法都重写了,优先调用methodMissing,其次是invokeMethod

    /**
     * 一个方法找不到时,调用它代替
     */
    def invokeMethod(String name,Object args){
        return "the method is ${name},the params is ${args}"
    }

    def methodMissing(String name,Object args){
        return "the method  ${name} is missing"
    }
//调用person中不存在的方法,编译时不会报错,运行时会异常
person.decrease()//Caught: groovy.lang.MissingMethodException
//重写了Person的invokeMethod方法之后,编译运行都不会出错
println person.decrease()//the method is decrease,the params is []
//如果重写了methodMissing方法,输出的是the method  decrease is missing

4.2.2 metaClass 注入新的属性和方法

动态扩展使用场景,当我们使用第三方类库却抱怨其方法不够全的时候,使用groovy为第三方类库添加方法无需像java那样使用继承

//为类动态的添加一个sex属性
Person.metaClass.sex = 'male'
def person2 = new Person(name:'Android',age:29)
println person2.sex//male
person2.sex = 'female'
println "the new sex is"+person2.sex//the new sex isfemale
//为类动态的添加方法
Person.metaClass.sexUpperCase = {_-> sex.toUpperCase()}
println person2.sexUpperCase()//FEMALE
//为类动态的添加静态方法
Person.metaClass.static.createPerson={
    String name,int age ->new Person(name:name,age:age)
}
def person3 = Person.createPerson('groovy',6)
println person3.name + " and " +person3.age//groovy and 6

4.2.3 ExpandoMetaClass.enableGlobally()全局注入

如果在一个类中为另外一个类拓展了一个新的方法,那么这个方法将不可以被全局使用,添加ExpandoMetaClass.enableGlobally()语句可以实现这个拓展方法的全局使用
可以简单编写一个程序模拟一下

// 模拟Person管理器
class PersonManager {
    static Person createPerson(String name,int age){
        return Person.createPerson(name,age)
    }
}
//模拟应用程序管理器
class AppliactionManager {
    static void init(){
        //一次注入拓展方法,全局都可以使用
        ExpandoMetaClass.enableGlobally()
        //为第三方类添加方法
        Person.metaClass.static.createPerson = {
            String name,int age ->
                new Person(name:name,age:age)
        }
    }
}
//模拟程序入口
class Entry {
    static void main(String[] args) {
        println '一个应用程序正在启动...'
        //初始化
        AppliactionManager.init()
        println '应用程序初始化完成'
        def person = PersonManager.createPerson( 'groovy',6)
        println "new person name is ${person.name},age is ${person.age}"
        //输出 new person name is groovy,age is 6
    }
}