[TOC]
Groovy是一门jvm语言,特定领域的语言.
打开Android Studio,随便新建一个Android项目.点击顶部Tools->Groovy Console即可,这时AS会出来一个窗口,专门拿来运行那种临时的Groovy代码的.因为是在本地执行,所以执行速度会非常快.写好代码后点击窗口左上角的三角按钮即可运行代码.
基础
变量
包含基本类型和对象类型;同时变量又包含强类型(类似 java 中的固定类型)和弱类型(类似 JS 中的弱类型)
强类型定义: 类似 java 中的定义边变量方式
弱引用定义: 用 def 关键字 定义一个变量
基本类型和引用类型
基本数据类型,同 java 中,包含 boolean,int,double,float,byte,char.
对象类型比如 Double,String等,完全跟 java 互通!
用法跟 java 用法一致,无需多讲...
// 基本数据类型
int a = 1 //定义 int 型数据
String s1 = "a" // 定义 String 类型数据-通过双引号
String s2 = 'a' // 定义 String 类型数据-通过单引号
boolean b1 = false // 定义布尔类型数据
double d = 1 // 定义 double 类型数据
double d2 = 3.0
float f = 2
def b = 2 // 弱引用类型
def s = "a" // 弱引用类型,通过赋值表明类型
字符串
在 Groovy 中字符串分为 java.lang.String 和 groovy.lang.String 两大类. 第一个就是我们常用的 java 中的 String 类,用法并无任何差异; 第二个是 Groovy 中的
String
同 java 中的 String 类,一毛一样...
GString
有三种常见的定义方法:
单引号定义
def gString = 'a'
但是通过打印gString.class
发现得到的是java.lang.String
,所以结论是通过单引号来定义得到的其实是 java 中的 String 对象
三个单引号定义
def gString2 = """ab"""
同上,得到的也是 java 中的 String
其实跟用单引号定义么啥大的区别,无非就是保持了格式.比如字符串里边包含单引号的话,不需要转义处理了.
双引号定义
def gString3 = "abc"
println(gString3.class) // class java.lang.String
用双引号发现,也是 java 中的 String...
def hello = "hello ${gString}"
println(hello)
println(hello.class) // class org.codehaus.groovy.runtime.GStringImpl
通过${}拼接之后,生成的就是 GString 了...
新增操作符
具体可查看 API,下边列几个常用的...
1.String[int index]
在 java 中可以直接使用 String.charAt(index)获取 index 位置的字符,在 Groovy 中获取字符串的某个位置的字符可以直接 String[index],其实等同于 java 中的 charAt(), []中的参数可以是某一个具体的 index,也可以是区间,比如[0..2]就表示获取字符串中的前 3 个字符.具体看如下代码
def str = "abcdefg"
println(str.charAt(2)) // c
println(str[2]) // c
println(str[0..2]) // abc
2. -
做减法.直接看示例
def strLong = "hello-world"
def strShort = "hello-"
println("${strLong - strShort}") // 输出:world
3.倒序
println("${strLong.reverse()}") // 输出:dlrow-olleh
4.首字母大写
println("${strLong.capitalize()}") // 输出:Hello-world
5.是否是数字
println("a".isNumber()) // false
println("1".isNumber()) // true
数组/集合
在 Groovy 里边数组和集合是一回事,都统称为集合吧..
在 Groovy 中集合可以存放不同类型的数据,而且比 java 中的更加强大,
// 定义一个数组
def arr = []
def arrMut = [1, "a", false, 4] // 存放不同类型数据
// 往数组中添加数据
arr[0] = "a"
arr[1] = "b"
println(arr) //[a,b]
// 根据索引值获取对应的值
println(arr[1]) // b
数组的遍历,可以采用两种方式: for 循环遍历;each()方法遍历
// 遍历数组
// 1.for 循环遍历
for (index in 0..arr.size() - 1) {
println("arr 中的元素:${arr[index]}")
}
// 2.each{} 遍历
arr.each {
println("arr 中的数据:${it}")
}
map
作为键值对的 map 结构,定义起来其实跟数组定义差不多..直接看代码即可
def map1 = ["key1": "value1", "key2": "value2"]
map 中提供了 each
方法方便于遍历
// 遍历 map
map.each { k, v ->
println("map: key = $k value = $v")
}
IO
API
// IO 操作
def file = new File("../file.txt")
file.eachLine {line, lineNo->
println "lineNo=$lineNo $line"
}
方法
Groovy 中的方法,定义跟java 中没啥区别,但是它有自己的一些特性.
括号可以省略
正常方法的写法如下:
// 定义方法
def method1(param1, param2) {
println("param1 = $param1, param2 = $param2")
}
// 调用方法
method1(1, 2) // 输出:param1 = 1, param2 = 2
在 Groovy 中可以直接这么调用
method1 5, 6 // 输出: param1 = 5, param2 = 6
可见可以直接省略掉括号直接进行方法的调用.
return 可以省略
如果省略掉 return 语句,那么 Groovy 中会默认将最后一行当做 return 语句的返回值
下边两个方法的作用一样
def returnMethod(int param) {
return 100 * param
}
def returnMethod(int param) {
100 * param
}
类-JavaBean
在 java 中定义 Bean,我们需要提供 set/get 方法,但是在 Groovy 中,完全没必要,直接使用就行,有点类似于 kotlin 中的 data class 似的.
User user = new User()
println("user.name = ${user.name}")
user.name = "xiaoming"
println("user.name = ${user.name}")
// 输出:user.name = null
// user.name = xiaoming
class User {
private String name
}
逻辑控制
顺序逻辑
条件逻辑
switch/case & if/else
Groovy中的switch/case和Java还是有点不同的.Java中的switch只支持固定的几种类型,但是Groovy中的switch是支持任意类型的,所以说基本上switch是可以代替if/else了.
def x = 100
def result
switch (x) {
case 1:
result = "result = 1"
break
case 100:
result = "result = 100"
break
case "hello":
result = "result = hello"
break
case BigDecimal:
result = "result = big decimal"
break
default:
result = "default"
}
println(result) // result = 100
循环逻辑
Groovy 中的循环逻辑,包含对范围的 for 循环;
对范围的 for 循环
def sum = 0
for (i in 0..10) {
sum += i
}
println("sum = $sum") // sum == 55
对 List 循环
def list1 = [1, 2, 3, 4, 5, 6]
for (i in list1) {
println(i)
}
对 map 循环
比 java 中遍历 map 方便多多多了...
def map1 = ["key1": "value1", "key2": "value2"]
for (i in map1) {
println("遍历 map: key = ${i.key} value = ${i.value}")
}
闭包
闭包就是一段代码块.
有点类似 kotlin 中高阶函数
可以将闭包当做参数传入方法中去,也可以赋值给变量,然后通过call
方法调用闭包,kotlin 中是使用的invoke
方法调用
如下定义一个最简单的闭包:
def b1 = {
println "Hello Closure"
} // 定义一个闭包 b1
b1.call() // 输出:Hello Closure
定义有参数的闭包:
// 有参数的闭包
def b2 = { key, value ->
println "key = $key, value = $value"
}
b2.call("id", 123) // 输出:key = id, value = 123
有返回参数的闭包:
// 有参数&返回值的闭包
def b2 = { key, value ->
println "key = $key, value = $value"
return "$key-$value"
}
def r = b2.call("id", 123) // 输出:key = id, value = 123
println(r) // 输出:id-123
闭包的 this,owner,delegate
闭包关键变量(this、owner、delegate)
def b3 = {
println "this:$this"
println "owner:$owner"
println "delegate:$delegate"
}
b3.call()
// 打印结果:
//this:ideaGroovyConsole@1b919693
//owner:ideaGroovyConsole@1b919693
//delegate:ideaGroovyConsole@1b919693
通过 LOG 可以看到,this,owner,delegate 返回的日志都是一致的.有猫腻...
- this: 这个关键字同 java 中的 this,表示当前类的方法或者变量,在 Groovy 中表示的是闭包定义处的类
- owner: 表示的是闭包定以处的类或者对象
- delegate:表示任意对象,默认与 owner 一致
进阶
数据结构-列表
列表的定义
在Java中我们定义一个列表一般是这样定义的List list = new ArrayList() 或者 new LinkedList()等等.
在我们Groovy中定义一个列表只需要让它等于[]
即可,也就是def list = []
,我们想要往里面添加元素直接往方括号里面加,用逗号隔开就行,比如def list = [1, 2, 3],这里呢会有同学有疑问,这个明明就是Java中的数组嘛,为什么到这里就变成List了呢?这个List是ArrayList还是LinkedList呢?别着急,我们打印下它的类型
def list = [1, 2, 3]
println list.class // 输出:class java.util.ArrayList
通过输出可以看到,此种定义方式的格式默认是 ArrayList 的,那么我们该怎么定义一个数组呢?很简单,可以直接使用as
进行强转,或者使用强类型定义
// 定义数组的两种方式:
// 第一种:使用[as]关键字,将 List 强转成数组
def arr1 = [1, 2, 3] as int[]
// 第二种:使用强类型直接定义
int[] arr2 = [1, 2, 3]
println arr1.class // 输出:class [I
println arr2.class // 输出:class [I
同理,我要想实例化一个 LikedList,那么也可以参考数组的定义方式来实现,采用两种方式来定义:
// 定义一个 LinkedList
def linkedList1 = [1, 2, 3] as LinkedList
LinkedList linkedList2 = [1, 2, 3]
println linkedList1.class // 输出:class java.util.LinkedList
println linkedList2.class // 输出:class java.util.LinkedList
列表的常见操作
主要针对增加,删除,查找,排序
增加
1.add()
增加的方法也是add()
,跟java 中一样,有两种添加方式:一种是在最后插入元素;另一种是在指定位置插入指定元素
// 增加
def addList = [1, 2, 3]
addList.add(4) //在最后添加一个元素
addList.add(0, 0) // 在指定位置添加元素
println addList // [0, 1, 2, 3, 4]
2.leftShift() 或者 <<
使用leftShift或者<<方法,表示在集合的最后添加一个元素,leftshift()的重载运算符是<<
// 增加-leftShift
addList.leftShift(5)
addList << 6
println addList // [0, 1, 2, 3, 4, 5, 6]
3.直接使用 +
还可以直接使用+
号进行拼接
// 增加-直接使用加号
addList = addList + 7
println addList // [0, 1, 2, 3, 4, 5, 6, 7]
删除
1.remove()
类似 java,直接使用remove(Object o)
或者remove(int index)
进行删除,其他的还有removeAll()
,removeElement()
类似,可自查
def deleteList = ["A", "B", "C"]
// 删除-使用 remove
deleteList.remove("C") // 输出:[A, B]
deleteList.remove(0) // 输出:[B]
deleteList.removeAt(0) // 内部实际调用了上边的 remove(index)方法
2.使用减号处理
// 删除-使用减号
deleteList = deleteList - "C"
查找
1.get(index)/List[index]
等同于 java 中的 get(index)方法或者 kotlin 中的[index]
// 查找-get()方法
def searchList = [1, 2, 3, 4, 5]
println "第二个元素是:${searchList.get(2 - 1)}" // 第二个元素是:2
println "第三个元素是:${searchList[3 - 1]}" // 第二个元素是:3
2.find(Closure closure)
返回符合闭包内条件的第一个元素
//查找-find 返回第一个符合条件的元素
def findResult = searchList.find { it ->
(it % 3) == 0
}
println "findResult = $findResult" // findResult = 3
3.findAll(Closure closure)
返回所有符合条件的元素
//查找-返回所有符合条件的元素
println searchList.findAll { it ->
(it % 2) == 0
} // [2, 4]
4.any(Closure closure)
any()
只要集合中有一个符合条件的,就返回 true
//查找-any: 只要有符合条件的就返回
println searchList.any { it ->
(it % 3) == 0
} // true
5.every(Closure closure)
every()
只有当所有的元素都符合条件时,才返回 true
//查找-every:所有元素都符合条件才返回 TRUE
println searchList.every { it ->
(it % 2) == 0
} // false
6.min()/max()
minx()
/max()
分别返回最小的元素和最大的元素
//查找-返回最小/大值
println searchList.min() // 1
println searchList.max() // 5
7.count()
返回符合条件的元素的个数
// 查找-count:返回符合条件的元素的个数
def count = searchList.count { it ->
(it % 2) == 0
}
println "对 2 取余为 0 的个数为:$count" // 2个
数据结构-映射
映射的定义
其实就是 java 中的 Map 操作.
在 java 中我们这么定义 Map:Map map = new HashMap()
, 在 Groovy 中的定义方式跟集合差不多,集合中是单元素的,映射是键值对形式的,也就是每个元素都是key:value
的形式.
def defMap = ["name": "Tom", "age": 18, "man": true]
println defMap // [name:Tom, age:18, man:true]
类似集合,我们打印一下这个 Map 是哪种类型的?
println defMap.getClass() // class java.util.LinkedHashMap
所以,如果你想定义别的 Map 类型,可以采用等同于集合的处理方式:第一种通过as
关键字进行强转;第二种通过强类型定义来定义
映射的常见操作
1.添加元素
添加元素有put()
方法,以及中括号直接操作,点操作;添加多个用putAll()
假如新添加的元素不存在,那么就直接添加;如果已经存在了,那么就会替换对应的 value
// 添加元素
defMap.put("height", 100)
defMap["birthday"] = "2011-11-11"
defMap.father = "Jack"
// 此时输出:[name:Tom, age:18, man:true, money:200.56, height:100, birthday:2011-11-11, father:Jack]
2.删除元素
针对删除元素,目前常用的就是remove()
方法
// 删除元素
defMap.remove("birthday")
3.根据key 获取 value
通过 key 获取 value ,Groovy 有提供get()
,getAt()
方法,同时也提供了方便的操作符获取,比如直接.
或者[]
来获取
def defMap = ["name": "Tom", "age": 18, "man": true, "money": 200.56]
println "key为 name 的 value 是:${defMap.name}"
println "key为 name 的 value 是:${defMap.get("name")}"
println "key为 name 的 value 是:${defMap["name"]}"
println "key为 name 的 value 是:${defMap.getAt("name")}"
//上述 4 种方法的输出都是: key为 name 的 value 是:Tom
4.遍历
遍历主要用到两个方法:each()
和eachWithIndex()
,第二个方法会附带输出当前索引值.
// 遍历
defMap.each {
println "key=${it.key}, value=${it.value}"
}
defMap.eachWithIndex { Map.Entry entry, int i ->
println "i=$i, key=${entry.key}, value=${entry.value}"
}
输出信息:
key=name, value=Tom
key=age, value=18
key=man, value=true
key=money, value=200.56
key=height, value=100
key=father, value=Jack
i=0, key=name, value=Tom
i=1, key=age, value=18
i=2, key=man, value=true
i=3, key=money, value=200.56
i=4, key=height, value=100
i=5, key=father, value=Jack
5.条件查找
跟 List 差不多,find()
,findAll()
,count()
数据结构-范围
在 Groovy 中,有个 范围
的数据结构,其实也很简单,比如要定义一个 1 到 10 的范围,就直接def a = 1..10
就行了, 主要用到了..
操作符.
其实所谓的范围,本质上是一个 List.
// 定义一个范围
def rangeInt = 1..10 // class groovy.lang.IntRange
def rangeString = "A".."D" //class groovy.lang.ObjectRange
常用操作
1.获取范围中某个值
// 获取范围中某个值
println rangeInt.get(1) // 索引值为 1 的数字是 2
println rangeInt[1]
2.范围中是否包含某个值
// 范围中是否包含某个值
println rangeInt.contains(4) // 存在则返回 true
3.获取范围第一个/最后一值
在范围的类定义中,有两个属性:from
,to
,对应的就是当前范围的第一个和最后一个值.
// 获取范围的第一个值
println rangeInt.from // 1
// 获取范围最后一个值
println rangeInt.to // 10
4.遍历
// 遍历
rangeInt.each {
println it
}