Groovy使用指南


 

groovy简介

Groovy是一种基于 JVM 的编程语言,结合了 python、ruby 和 Smalltalk 的许多强大的特性,面向对象,Groovy 可以与 Java 代码很好地结合,可以直接在groovy中写java代码,既可以用于面向对象编程,又可以用作纯粹的脚本语言。
 

groovy的主要特点

  • 同时支持静态、动态类型
  • 支持各种标记语言,比如原生支持xml、html
  • 支持闭包
  • 可以在groovy中直接写java代码,可以直接使用现有的java类库,相比于java,groovy更加简洁;
  • groovy语法和java非常相似,易于java开发者掌握。

 

groovy类的基本特点

  • 一个.groovy文件中可以包含多个public类,不要求public类的类名月文件名相同;
  • 默认访问修饰符是public,如果类、成员使用public修饰,可以缺省public;
  • 支持动态类型,不管是变量还是方法返回类型,都不需要声明类型;
  • 语句末尾的分号不是必需的,可以省略;
  • 注释和java相同。
     

groovy 默认会导入以下包、类,无需 import 显式导入

import java.lang.* 
import java.util.* 
import java.io.* 
import java.net.* 

import java.math.BigInteger 
import java.math.BigDecimal

import groovy.lang.* 
import groovy.util.* 

groovy在 java.lang.Object 的基础上进行了扩展,相比于java的Object类,groovy中的Object类具有更多的方法。

 

在java项目中引入groovy

很少直接用groovy写一整个大项目,一般是搭配java使用,用来写部分模块、服务、脚本。

pom.xml

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>3.0.9</version>
    <type>pom</type>
</dependency>

 

定义变量

groovy自动导入了 java.lang,可以使用java的数据类型

//可以使用具体类型,也可以声明为 def 任意类型、动态类型

int x
int y = 5

def x
def y = 5

 
在groovy中,对于自带类型,== 相当于 equals

//true 通过
assert new String("xxx") == new String("xxx")

 

groovy中的常见类型

字符串

groovy的字符串可以用单引、双引、三引定义,单引中可以使用双引,双引中可以使用单引,三引中可以使用单、双引。

三引类似 html 的 <pre> 标签,可以保证内容格式不变。

//单双引
def str1 = 'hello world'
def str2 = "hello world"

//三引
def str3 = '''hello world'''
def str4 = """hello world"""

 

模板字符串

def user = new User(1, "chy")

//字符串内可以通过 ${} 引用变量,可以访问属性、调用方法
println("user: ${user}")
println("name: ${user.name}")
println("name:${user.getName()}")

//直接访问对象本身或属性时,可以缺省{},调用方法时则不能缺省{}     
println("user:$user")
print("name:$user.name")

双引中的 $表达式 才会被解析,单引、三引中的 $表达式 会被当做普通字符串处理。
 

与java不同,groovy中的字符串可通过下标直接索引

def str = "hello world"

//java中可以通过 charAt() 来获取指定位置的字符,但不能直接 [n] 以数组下标方式直接操作
//groovy可以以[n] 数组下标方式来获取字符串指定位置的字符,但不能通过 [n] 来给字符串指定位置赋值
//数组则可以通过 [n] 直接取值、赋值
println str[0]

//取 [0,4] 上的字符串
println(str[0..4])

//先取 [0,4] 上的字符串,再将字符串反序排列
println(str[4..0])

//将字符串重复指定次数,java中没有此操作
println(str * 3)

 

数组 、列表 list

在 groovy 中

  • 大括号是留给闭包(closure)使用的,数组、列表都使用中括号进行定义;
  • 数组、列表的元素都有序,可通过下标索引;
  • 区别:数组元素类型相同,列表元素类型可以不同。
//java中定义数组
int[] array = {1, 2, 3};

//groovy中定义数组
int[] array = [1, 2, 3]

//groovy中定义列表
def list = [1, 2, "zhangsan"]
//支持嵌套
def list3 = [1, 2, ["zhangsan", "lisi"]]

 
列表常用方法

def list1 = [1, 2]
def list2 = [3, 4]


//在指定位置添加元素,index范围只能是 [0, size]
list1.add(0, "lisi")
//缺省index时默认添加到末尾
list1.add("wangwu")

//add是把参数作为一个元素进行添加,参数是集合时,会整个集合作为一个元素添加
list1.add(list2)
//如果要将其它集合中的元素都添加到当前集合汇总,可以用 plus 或 + ,返回副本
list1 = list1 + list2
// list1 = list1.plus(list2)


//添加是add、plus(+),移除是remove、minus(-),使用方式相同,add => remove,plus => minus


//元素反序排列,返回副本
list1 = list1.reverse()

//元素排序,直接修改的原list。默认自然排序,可自定义排序规则
list1.sort()

 
列表的遍历

def list = ["zhangsan", "lisi", "wangwu"]

//传统for循环方式
for (def ele : list) {
    println(ele)
}
for (i in 0..<list.size()) {
    println(list[i])
}

//lambda表达式
list.each { ele -> println(ele) }

//闭包
list.forEach({ ele -> println(ele) })
list.iterator().forEachRemaining({ ele -> println(ele) })

 

元祖 tuple
  • tuple是一种特殊的list,和list一样元素有序、类型可以不同,可以通过下标来访问。
  • 与list的区别:不能增删、修改元素(引用类型可以修改内部属性值,但不能修改引用本身),否则会抛出 UnsupportedOperationException。
  • IDE代码提示中有 add()、remove() 之类的方法,但那是list的方法,tuple实际是不能使用的。
//Tuple 元素数量不限
def tuple = new Tuple(10, "zhangsan", true, new Person())

//可以通过下标来访问
println tuple.get(0)
println tuple[0]
println tuple[0..2]


//Tuple 1~9,元素最多只能为指定数量,eg. Tuple1 元素最多1个、最少0个
def tuple1 = new Tuple1(10)
println tuple1.first

def tuple2 = new Tuple2(10, "zhangsan")
println tuple2.second

def tuple3 = new Tuple3(10, "zhangsan", true)
println tuple3.third

 

映射 | 字典 | map

映射也叫作字典、map

def userInfo = ["name": "chy", "age": 20]

//更新key对应的value
userInfo.name = "zhangsan"

//获取key对应的value
println(userInfo.name)
println(userInfo.get("name"))

 
转换为实体类

def map = ["id": 1, "name": "chy"]

//as转换为指定类型,也可以直接用java格式的 (Person) map
def person = map as Person

 

范围运算符 …

//[1,10] 总共10个数字
def range1 = 1..10

//[1,10) 总共9个数字
def range2 = 1..<10

//支持 降序|反序 排列
def range3 = 10..1

//支持字符
def range4 = 'A'..'D'

本质是一种特殊的 list,可以使用 list 的操作方式,比如 [index] 访问指定位置的元素。
 

常用方法

//是否是反序排列
println(range.reverse)
println(range.isReverse())

println(range.size())

println(range.sum())

println(range.contains(1))

println(range.get(0))
//获取最小元素,包装类型
println(range.from)
println(range.getFrom())

//获取最小元素,基本类型
println(range.fromInt)
println(range.getFromInt())


//获取最大元素,包装类型
println(range.to)
println(range.getTo())

//获取最大元素,基本类型
println(range.toInt)
println(range.getToInt())


//获取首尾元素
println(range.first())
println(range.last())

//子区域 [0,5]
def list = range.subList(0, 5)

//注意:from、to不是range的首尾元素,而是range中最小、最大的元素

 

切片

arr、list、tuple、string 都可以用范围运算符进行切片

def list = [1, 2, 3, 4, 5]

//[0,1]。相当于subList(),区别在于范围运算符左右都是闭合,subList()是左开右闭
def list1 = list[0..2]

//[0,2)
def list2 = list.subList(0, 2)

 

方法定义、调用

  • 方法可以使用 private、static、final 之类的关键字修饰,缺省访问权限时,默认为 public;
  • groovy的 main 方法声明与 java 相同,只是默认就是public,缺省了关键字 public。
//显式指定类型
int sum(int a, int b) {
    return a + b
}


//参数可以不指定类型,不指定类型时为 def
def sum(a, b) {
    return a + b
}

//运行时会根据实参确定参数类型,可以实现函数重载
sum(1, 2)
sum("hello", " world")


//默认参数:放在形参表末尾,调用时可传可不传
def sum(a, b = 0, c = 0) {
    return a + b + c
}

sum(1)
sum(1, 2)

如果方法要给其他人使用,使用 def 有一个很大的缺点,调用者不知道参数要传什么类型、返回值要传什么类型,所以groovy常用于编写单人开发的模块、脚本,很少成为项目的主体语言。
 

方法调用可以缺省小括号,构造函数除外

def user = new User(1, "chy")

//使用()
println(user.name)
printf("user:%s", user)

//不使用()
println user
printf "user:%s", user

 
运行时分派:对应函数重载,groovy是以运行时实参的实际类型来进行方法调用

int method(String arg) {
    return 1;
}

int method(Object arg) {
    return 2;
}


//虽然实参声明为Object,但实际为String,所以实际调用的是第一个方法
Object o = "Object";
int result = method(o);

 

闭包

闭包(closure)是一个短的匿名代码块,使用大括号定义

//定义闭包
def closure1 = { println("xxx") }
//执行闭包中的代码块
closure1.call()

//可以包含多行代码
def closure2 = {
    println("xxx")
    println("yyy")
}
//闭包可以使用参数,像定义方法一样
def closure1 = { param -> println(param) }
closure1.call("xxx")


//支持多个参数,多个参数不需要像lambda表达式一样放在小括号中
def closure2 = {
    param1, param2 -> println(param1 + param2)
}
closure2.call(1, 2)
closure2.call("xxx", "yyyy")


//参数可以声明具体的类型
def closure3 = {
    int param1, int param2 -> println(param1 + param2)
}


// -> 后有多行代码时,不需要像lambda表达式一样,放在大括号中
def closure4 = { param1, param2 ->
    println(param1)
    println(param2)
}
def file = new File("D:/document/1.txt")

//闭包可以作为函数参数
file.withWriter({ write -> write.write("xxx") })
file.withWriter("utf-8", { write -> write.write("xxx") })


//如果函数体本身的操作就是调用闭包,可以将闭包写成函数体形式
file.withWriter {
    write -> write.write("xxx")
}
file.withWriter("utf-8") {
    write -> write.write("xxx")
}

 

类的定义

class Person {
    Integer id
    String name

    static void main(String[] args) {
        //使用自动提供的map型参数的构造方法
        def person1 = new Person(["id": 1, "name": "chy"])
        
        //可以缺省[]
        def person2 = new Person("id": 1, "name": "chy")
        
        //或者使用java的map
        def map = new HashMap<String, Object>()
        map.put("id", 1)
        map.put("name", "chy")
        def person3 = new Person(map)
    }

}

 
1、groovy 的访问权限控制符默认是 public,一般也是使用 public。
 

2、groovy会自动给 public 型成员(包括static成员)添加 getter、setter 方法,实例成员通过实例访问,静态成员通过类名访问。

可以直接通过属性名访问(实质是调用对应的getter、setter方法),也可以通过getter、setter方法访问,或者通过字符串属性名形式的 getProperty()、setProperty() 方法访问。
 

3、如果没有给 groovy 类显式提供构造器,在 groovy 中会自动提供无参构造器、map型参数的构造器,java 中调用 groovy 类时,则只提供无参构造器
 

4、在 groovy 类中使用 lombok 的注解会失效,部分注解可以使用 groovy-all 提供的,如下

@Slf4j
@Builder
@ToString
@EqualsAndHashCode

 

IO

groovy 自动导入了 java.io,可以使用 java 的 io,也可以使用 groovy 的 io,此处介绍 groovy 的 io。
 

控制台输出
print(user.name)
println(user.name)
printf("user:%s", user)

 

File类

groovy 的 File 类是在 java File 类的基础上进行增强,提供了更多、更简便的方法

File file = new File("D:/document", "1.txt")
File file1 = new File("D:/document/1.txt")

//获取File对象信息
println(file.name)
println(file.getName())
println(file.isDirectory())

 

文件读
//获取文本文件的全部内容
def text1 = file.text
def text2 = file.getText()
def text3 = file.getText("uft-8")

//获取包含全部内容的字节数组,byte[]
def bytes1 = file.bytes
def bytes2 = file.getBytes()
//逐行遍历
file.eachLine {
    line -> println(line)
}

//闭包可以缺省临时变量,直接使用默认的临时变量名 it
file.eachLine {
    println(it)
}

//可以指定字符集
file.eachLine('utf-8') {
    println(it)
}

//可以携带行号
file.eachLine { line, lineNumber ->
    println("第${lineNumber}行:$line")
}


//收集每一行到list中,一行即一个元素
def list = file.collect()

//收集每一行到数组中
def arr = file.collect() as String[]
//可以使用 InputStream。手动关闭
def fis1 = file.newInputStream()
//...
fis1.close()

//自动关闭
file.withInputStream {
    fis2 -> //...
}


//也可以使用 Reader
def reader1 = file.newReader()
//...
reader1.close()

file.withReader {
    reader -> //...
}


//Reader可以指定字符集
def reader2 = file.newReader("utf-8")
//...
reader1.close()

file.withReader("utf-8"){
    reader -> //...
}

 

文件写

groovy的写操作,如果指定的文件不存在,都会先自动创建再写入

//文本文件可以直接设置内容
file.text="xxx"
file.setText("xxx")
file.setText("xxx","utf-8")

//也可以用 bytes、setBytes() 写入byte[]

//都是覆盖:先删除全部原内容,再写入
//可以使用 OutputStream
file.withOutputStream {
    fos2 -> //...
}


//也可以使用Writer。覆盖
file.withWriter { write ->
    write.write("xxx")
}

//追加
file.withWriterAppend { write ->
    write.write("xxx")
}


//Writer可以指定字符集
file.withWriter("utf-8") { writer ->
    writer.write("xxx")
}

file.withWriterAppend("utf-8") {
    write -> //...
}
//都可以手动关闭

def fos1 = file.newOutputStream()
//...
fos1.close()


def writer1 = file.newWriter()
//是否是append 追加,默认false 直接覆盖
def writer2 = file.newWriter(true)
def writer3 = file.newWriter("utf-8")
def writer4 = file.newWriter("utf-8", true)
//...
writer1.close()
writer2.close()
writer3.close()
writer4.close()


def printWriter1 = file.newPrintWriter()
def printWriter2 = file.newPrintWriter("utf-8")
//...
printWriter1.close()
printWriter2.close()
def src = new File("D:/document/1.txt")
def dest = new File("D:/document/2.txt")

//追加也可以用运算符 <<
src << '''
        Into the ancient pond
        A frog jumps
        Water’s sound!
    '''

//把一个文件的内容拷贝到另一个文件中(复制),<< 都是以追加形式写入的
dest << src.text

 

遍历文件树
def dir = new File("D:/笔记")

//遍历直接子文件、子文件夹,只遍历直接的
dir.eachFile() {
    file -> println(file.absolutePath)
}

//递归遍历所有的文件、文件夹
dir.eachFileRecurse() {
    file -> println(file.absolutePath)
}


//可以筛选类型,FILES 文件、DIRECTORIES 目录,默认为 ALL
dir.eachFile(FileType.DIRECTORIES) {
    file -> println(file.absolutePath)
}

dir.eachFileRecurse(FileType.FILES) { 
	file -> println(file.absolutePath)
}
//eachFile包含了文件、文件夹,eachDir则只包含文件夹

//遍历直接子文件夹
dir.eachDir {
    dir1 -> println(dir1.absolutePath)
}

//递归遍历所有的文件夹
dir.eachDirRecurse() {
    dir1 -> println(dir1.absolutePath)
}

 

说明

1、闭包可以缺省临时变量,直接使用默认的临时变量名 it,it 即 item 的简写。
 
2、groovy的自动资源管理

groovy提供的闭包形式的IO操作,实质是对 try…finally 的封装,即使执行时发生了异常,也会自动关闭资源,无需手动关闭。
 
3、可以使用基于字节的 InputStream、OutputStream,也可以使用基于字符的 Reader、Write,基于字符的IO流都可以指定字符集。

 

单元测试

继承 GroovyTestCase,方法名以 test 开头,空参,返回值类型 void

import org.junit.Assert

class Test1 extends GroovyTestCase {

    void testXxx() {
        def str = "xxx"
        //groovy的断言
        assert "xxx1" == str
        //也可以用junit的断言
        Assert.assertEquals("xxx", str)
    }

}

 
可以用 GroovyTestSuite 组装多个要执行的测试类,用 TestRunner 执行批量测试

class AllTest extends GroovyTestCase {

    void testAll() {
        //组装要执行的多个测试类
        def allTest = new GroovyTestSuite()
        allTest.addTestSuite(Test1.class)
        allTest.addTestSuite(Test2.class)

        //执行测试
        TestRunner.run(allTest)
    }

}
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Android Gradle权威指南》是一本介绍如何使用Gradle构建Android应用程序的权威指南。本书详细介绍了Gradle的基本概念、构建脚本的编写、依赖管理、多模块构建、构建变体、构建优化等方面的内容。对于想要深入了解Gradle构建Android应用程序的开发者来说,这本书是一本非常好的参考书籍。 ### 回答2: 《Android Gradle权威指南》是一本详细介绍了Android Gradle构建系统的权威指南。Gradle是一种基于Groovy语言的构建自动化工具,而Android Gradle是针对Android应用开发的定制版本。 该指南从基础概念、Gradle的安装和配置开始介绍,随后介绍了Gradle构建脚本的语法和结构。读者将学会如何编写Gradle脚本以管理项目依赖、构建和打包Android应用。 此外,《Android Gradle权威指南》还深入介绍了Gradle的高级功能,如多模块项目管理、变体构建、构建缓存、增量构建等。读者将可以通过使用这些高级功能提高构建效率和减少构建时间。 该指南还对Android Gradle插件的特性进行了解释和演示。它详细介绍了如何使用插件进行代码混淆、资源压缩、构建变体等。此外,读者还能学到如何定制构建过程,处理不同环境和变体。 总的来说,《Android Gradle权威指南》是一本全面而深入的Gradle学习指南,适合已有Gradle基础的Android开发者。通过阅读本书,读者将能够更好地理解和使用Gradle构建系统,以及优化和自定义Android应用的构建过程。 ### 回答3: 《Android Gradle权威指南》是一本介绍如何使用Gradle构建Android应用程序的权威性参考书。Gradle是一种功能强大的构建工具,广泛应用于Android开发中,它以脚本方式定义构建过程,提供了高度灵活性和可扩展性。 这本书首先介绍了Gradle的基本概念和特点,包括项目结构、任务和依赖管理。然后,它深入解析了在Android开发中使用Gradle的各个方面。书中包含了大量实用的示例代码和详细的操作步骤,帮助读者更好地理解和掌握Gradle的使用。 《Android Gradle权威指南》的内容覆盖了Android项目的各个方面,包括构建类型、变体、签名、多模块项目、任务定制等。此外,它还介绍了如何使用Gradle进行自动化测试、发布和持续集成,以及如何优化构建速度和性能。 这本书的优点在于它权威而全面地介绍了Android开发中Gradle的使用,从基础知识到高级技巧都有涉及。同时,作者对相关概念和原理进行了深入讲解,使读者能够更好地理解Gradle的内部工作原理。 总之,对于想要更好地掌握Gradle在Android开发中的应用的开发者来说,《Android Gradle权威指南》是一本非常有价值的参考书。无论是初学者还是有一定经验的开发者,都能从中获得实用的技巧和知识,提升在Android开发中的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值