Groovy

一、Gradle简介

Gradle 是一个基于 JVM 的新一代构建工具

Groovy 是 Apache 旗下的一种基于JVM的面向对象编程语言,既可以用于面向对象编程,也可以用作纯粹的脚本语言。在语言的设计上它吸纳了 Python、Ruby 和 Smalltalk 语言的优秀特性,比如动态类型转换、闭包和元编程支持。Groovy 与 Java 可以很好的互相调用并结合编程 ,比如在写 Groovy 的时候忘记了语法可以直接按 Java 的语法继续写,也可以在 Java 中调用 Groovy 脚本。比起 Java,Groovy 语法更加的灵活和简洁,可以用更少的代码来实现 Java 实现的同样功能。它即可以支持面向对象编程(基于 Java 的扩展),也可以支持面向过程编程(基于众多脚本语言的结合)。需要注意的是,在我们使用 Groovy 进行 Gradle 脚本编写的时候,都是使用的面向过程进行编程的。

二、基础语法

2.1 Groovy 中的变量

2.1.1 变量的类型

groovy 中是不存在基本类型,皆为对象类型。下面我们看个例子:

2.1.2 变量的定义
  • 强类型定义方式:在声明变量的时候定义它的类型,例如 int x=10。
  • 弱类型定义方式:通过 def 关键字来定义我们任何的变量,编译器会根据值的类型来推导它的类型。

2.2 字符串

在 Groovy 中有三种常用的字符串定义方式,如下所示:

  • 单引号 ’ ’ 定义的字符串
  • 双引号 " " 定义的字符串
  • 三引号 ‘’’ ‘’’ 定义的字符串
2.2.1 GString

双引号还可以定义一个可扩展的变量。

def groovyName="Groovy"
def say="hello ${groovyName}"
//${...} 里面不仅仅可以是变量,还可以是任意表达式
def sum = "The sum of 2 and 3 equals ${2+3}"
2.2.2 字符串方法
def str="groovy"
str.center(8,'a')//agroovya
srr.padLeft(8,'a')//aagroovy
def str2="hello"
//字符串比较
str>str2//true
//字符串索引
str[0]//g
str[0..2]//gro
//字符串减法
def m1="groovy hello"
def m2="groovy"
m1-m2//
//倒序
str.reverse()
//首字母大写
str.capitalize()
//判断是否是数字类型字符串
str.isInteger()

三、闭包

3.1 闭包基础讲解

闭包的本质其实就是一个代码块

定义和调用

//闭包定义
def clouser = { println 'hello groovy'}
//闭包调用
clouser.call()
clouser()
//一个参数,默认参数it
def clouser1={println "hello ${it}"}
//多个参数
def clouser2={String name , int age ->
  println "Hello ${name},age is ${age}"
}
//返回值
def result=clouser() //null

3.2 闭包使用讲解

3.2.1 闭包使用

groovy 闭包作为方法的最后一个参数是可以写在圆括号外面的

static int fab(int number){
  int result = 1
  //用来求制定number的阶乘
  number.downto(1){
    num -> result*=num
  }
  return result
}

int y=fab(5)//120

3.2.2 闭包与 String 的结合使用

String 的遍历方法:

String str='the 2 and 3 is 5'
//each遍历
str.each{
  String temp -> print temp.multiply(2)
}
//find 来查找符合条件的第一个
str.find{
  String s -> s.isNumber()
}
//与 find 方法成对的还有一个 findAll 方法
def list = str.findAll{
  String s -> s.isNumber()
}
list.toListString()//[2,3,5]

any 和 every:

String str='the 2 and 3 is 5'
//只要有一项符合条件就返回true
str.any{
    String s -> s.isNumber()
}
//每一项都符合条件就返回true
str.every{
    String s -> s.isNumber()
}

collect 方法:

String str = "hello world"
str.collect{
    //转换成大写
    it.toUpperCase()
}//[H,E,L,L,O, ,W,O,R,L,D]

3.3 闭包进阶讲解

3.3.1 闭包关键变量
def scriptClouser = {
    println "this :" + this
    println "owner :" + owner
    println "delegate :" + delegate
}
scriptClouser.call()

this、owner、delegate 分别代表的对象,如果是在类中定义的闭包,那么三者代表的是同一个对象。

闭包中再定义一个闭包,那么 this、owner、delegate 返回的就不一样了

默认情况下 owner 和 delegate 是相同的,

this 和 owner 是不可以修改的。

3.3.2 闭包委托策略

一共有四种委托策略:

public static final int OWNER_FIRST = 0;
public static final int DELEGATE_FIRST =1;
public static final int OWNER_ONLY =2;
public static final int DELEGATE_ONLY =3;

四、数据结构

4.1 list

list 即链表,其底层对应 Java 中的 List 接口,一般用 ArrayList 作为真正的实现类,List 变量由[]定义,其元素可以是任何对象。链表中的元素可以通过索引存取,而且不用担心索引越界。如果索引超过当前链表长度,List 会自动往该索引添加元素。

下面,我们看看 list 最常使用的几个操作。

排序

def sortList = [6,-3,9,2,-7,1,5]
Collections.sort(sortList)
//java中自定义排序规则,按绝对值大小排序
Comparator mc = {a,b -> a==b?0:Math.abs(a)<Math.abs(b)?-1:1}
Collections.sort(sortList,mc)
sortList.sort()
sortList.sort{a,b -> a==b?0:Math.abs(a)<Math.abs(b)?-1:1}

查找:

def findList = [-3,9,6,2,-7,1,5]
findList.find{return it%2==0}//6
def results=findList.findAll(){return it%2==0}
results.toListString()//[6,2]
//是否有一项满足条件
findList.any{return it%2!=0}
//是否都符合条件
findList.every{return it%2==0}
findList.min()
findList.max()
//统计有多少项符合条件
findList.count{return it>=0}

4.2 Map

上述的代码可以看出 groovy 的 map 操作跟 java 一样都是很简单的,下面我们来看看 map 常用的操作方法。

遍历:

def students = [1:[number:'0001',name:"A",score:55],2:[number:'0002',name:"B",score:83]]
strdents.each{def student ->
    println "the key is ${student.key},the value is ${student.value}"
}
strdents.each{key,value ->
    println "the key is ${key}, the value is ${value}"
}
//带索引的遍历
students.eachWithIndex{def student,int i ->
    println "index is ${i} , the key is ${student.key},the value is ${student.value}"
}
students.eachWidthIndex{key,value index ->
    println "index is ${index},the key is ${key},the value is ${value}"
}

查询:

//查找第一个符合条件的
students.find{
    def student -> return student.value.score>=60
}
//查找所有符合条件的
students.findAll{
    def student -> return student.value.score>=60
}
//计算所有符合条件的项数量
students.count{
    def student -> return student.value.score>=60
}
students.findAll{
    def student -> return student.value.score>=60
}.collect{
   return it.value.name
}

排序:

def sort = students.sort{
	def student1,def students ->
        Number score1=student1.value.score
        Number score2=student2.value.score
    	return score1==score2 ? 0 :score1<score2 ? -1:1
}
sort.toMapString()

五、面向对象

5.1 类、接口等的定义

groovy中类、接口等的定义和java基本一样,但是如果不声明 public/private 等访问权限的话,Groovy 中类及其变量默认都是 public 的。另外,groovy中还有一个 trait 关键字:

它的作用类似于接口,相比接口,它的方法可以有默认实现。有点适配器模式的味道。

5.2 元编程

元编程即Groovy运行时,它的逻辑处理流程图如下:

img

为了更好的讲解元编程的用法,我们先创建一个 Person 类并调用它的 cry 方法,代码如下所示:

// 第一个 groovy 文件中
def person = new Person(name: 'Qndroid', age: 26)
println person.cry()
// 第二个 groovy 文件中
class Person {
    String name
	Integer age
    def increaseAge(Integer years) {
        this.age += years
    }
    //一个方法找不到时,调用它代替
    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"
    }
}

为了实现元编程,我们需要使用 metaClass,具体的使用示例如下所示:

ExpandoMetaClass.enableGlobally()
//为类动态的添加一个属性
Person.metaClass.sex = 'male'
def person = new Person(name: 'Qndroid', age: 26)
println person.sex
person.sex = 'female'
println "the new sex is:" + person.sex
//为类动态的添加方法
Person.metaClass.sexUpperCase = { -> sex.toUpperCase() }
def person2 = new Person(name: 'Qndroid', age: 26)
println person2.sexUpperCase()
//为类动态的添加静态方法
Person.metaClass.static.createPerson = {
    String name, int age -> new Person(name: name, age: age)
}
def person3 = Person.createPerson('renzhiqiang', 26)
println person3.name + " and " + person3.age

需要注意的是通过类的 metaClass 来添加元素的这种方式每次使用时都需要重新添加,幸运的是,我们可以在注入前调用全局生效的处理,代码如下所示:

ExpandoMetaClass.enableGlobally()
// 在应用程序初始化的时候我们可以为第三方类添加方法
Person.metaClass.static.createPerson = { String name, int age ->    
    new Person(name: name, age: age)
}

5.3 脚本中的变量和作用域

对于每一个 Groovy 脚本来说,它都会生成一个 static void main 函数,main 函数中会调用一个 run 函数,脚本中的所有代码则包含在 run 函数之中。我们可以通过如下的 groovyc 命令用于将编译得到的 class 文件拷贝到 classes 文件夹下:

// groovyc 是 groovy 的编译命令,-d classes 用于将编译得到的 class 文件拷贝到 classes 文件夹 下
groovyc -d classes test.groovy

当我们在 Groovy 脚本中定义一个变量时,由于它实际上是在 run 函数中创建的,所以脚本中的其它方法或其他脚本是无法访问它的。这个时候,我们需要使用 @Field 将当前变量标记为成员变量,其示例代码如下所示:

import groovy.transform.Field; 
@Field author = lerendan

六、Groovy 高级用法

6.1、Json 操作

//对象转json字符串
def list = [new Person(name:"A",age:25),new Person(name:"B",age:26)]
def json=JsonOutput.toJson(list)
//带格式的输出
JsonOutput.prettyPrint(json)
//json字符串转对象
def jsonSlpuer =new JsonSlurper()
jsonSlpuer.parse()

6.2、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 xmlSlurper = new XmlSlurper()
def response = xmlSlurper.parseText(xml)
println response.value.books[0].book[0].title.text()

xml遍历

def list = []
response.value.books.each{ books -> 
    books.book.each{ book -> 
        def author =book.author.text()
        if(author.equals('李刚')){
            list.add(book.title.text())
        }	
    }
}
print list.toListString()//[疯狂Android讲义,Vue从入门到精通]

深度遍历和及广度遍历:

//深度遍历
def titles = response.depthFirst().findAll{ book ->
    //选取所有符合条件的节点
	return book.author.text() == '李刚'
}.collect{
    //只选中book下的title节点
    return it.title
}
println titles.toListString()
def title1=response.'**'.findAll{ book ->
	return book.author.text() == '李刚'
}
//广度遍历
def name = response.value.books.children().findAll{ node ->
    node.name() == 'book' && node.@id=='2'
}.collect{ node ->
    return node.title.text()
}

利用 XmlSlurper 在 Android 中获取 AndroidManifest.xml 里的信息:

def androidManifest = new XmlSlurper().parse("./app/src/main/AndroidManifest.xml")
println androidManifest.@'package'
6.3 文件处理
def file = new File('../../Test.tml')
//对文件遍历
file.eachLine{ line ->
	println line
}
def result = file.readLines()
println result.toListString()
//获取文件内容
def text = file.getText()
//读取文件部分内容
def reader = file.withReader{ reader ->
    //读取前100个字符
	char[] buffer =new char[100]
    reader.read(buffer)
    return buffer
}
//copy
new File(fromPath).withReader{ reader ->
    def lines = reader.readLines()
    toFile.withWiter{ writer ->
        lines.each{ line ->
            writer.append(line +"\r\n")
        }   
    }
}
//对象读写
desFile.withObjectOutputStream{ out ->
    out.writeObject(object)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值