[TOC]
Groovy是一門jvm語言,特定領(lǐng)域的語言.
打開Android Studio,隨便新建一個(gè)Android項(xiàng)目.點(diǎn)擊頂部Tools->Groovy Console即可,這時(shí)AS會(huì)出來一個(gè)窗口,專門拿來運(yùn)行那種臨時(shí)的Groovy代碼的.因?yàn)槭窃诒镜貓?zhí)行,所以執(zhí)行速度會(huì)非???寫好代碼后點(diǎn)擊窗口左上角的三角按鈕即可運(yùn)行代碼.
基礎(chǔ)
變量
包含基本類型和對象類型;同時(shí)變量又包含強(qiáng)類型(類似 java 中的固定類型)和弱類型(類似 JS 中的弱類型)
強(qiáng)類型定義: 類似 java 中的定義邊變量方式
弱引用定義: 用 def 關(guān)鍵字 定義一個(gè)變量
基本類型和引用類型
基本數(shù)據(jù)類型,同 java 中,包含 boolean,int,double,float,byte,char.
對象類型比如 Double,String等,完全跟 java 互通!
用法跟 java 用法一致,無需多講...
// 基本數(shù)據(jù)類型
int a = 1 //定義 int 型數(shù)據(jù)
String s1 = "a" // 定義 String 類型數(shù)據(jù)-通過雙引號
String s2 = 'a' // 定義 String 類型數(shù)據(jù)-通過單引號
boolean b1 = false // 定義布爾類型數(shù)據(jù)
double d = 1 // 定義 double 類型數(shù)據(jù)
double d2 = 3.0
float f = 2
def b = 2 // 弱引用類型
def s = "a" // 弱引用類型,通過賦值表明類型
字符串
在 Groovy 中字符串分為 java.lang.String 和 groovy.lang.String 兩大類. 第一個(gè)就是我們常用的 java 中的 String 類,用法并無任何差異; 第二個(gè)是 Groovy 中的
String
同 java 中的 String 類,一毛一樣...
GString
有三種常見的定義方法:
單引號定義
def gString = 'a'
但是通過打印gString.class
發(fā)現(xiàn)得到的是java.lang.String
,所以結(jié)論是通過單引號來定義得到的其實(shí)是 java 中的 String 對象
三個(gè)單引號定義
def gString2 = """ab"""
同上,得到的也是 java 中的 String
其實(shí)跟用單引號定義么啥大的區(qū)別,無非就是保持了格式.比如字符串里邊包含單引號的話,不需要轉(zhuǎn)義處理了.
雙引號定義
def gString3 = "abc"
println(gString3.class) // class java.lang.String
用雙引號發(fā)現(xiàn),也是 java 中的 String...
def hello = "hello ${gString}"
println(hello)
println(hello.class) // class org.codehaus.groovy.runtime.GStringImpl
通過${}拼接之后,生成的就是 GString 了...
新增操作符
具體可查看 API,下邊列幾個(gè)常用的...
1.String[int index]
在 java 中可以直接使用 String.charAt(index)獲取 index 位置的字符,在 Groovy 中獲取字符串的某個(gè)位置的字符可以直接 String[index],其實(shí)等同于 java 中的 charAt(), []中的參數(shù)可以是某一個(gè)具體的 index,也可以是區(qū)間,比如[0..2]就表示獲取字符串中的前 3 個(gè)字符.具體看如下代碼
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.是否是數(shù)字
println("a".isNumber()) // false
println("1".isNumber()) // true
數(shù)組/集合
在 Groovy 里邊數(shù)組和集合是一回事,都統(tǒng)稱為集合吧..
在 Groovy 中集合可以存放不同類型的數(shù)據(jù),而且比 java 中的更加強(qiáng)大,
// 定義一個(gè)數(shù)組
def arr = []
def arrMut = [1, "a", false, 4] // 存放不同類型數(shù)據(jù)
// 往數(shù)組中添加數(shù)據(jù)
arr[0] = "a"
arr[1] = "b"
println(arr) //[a,b]
// 根據(jù)索引值獲取對應(yīng)的值
println(arr[1]) // b
數(shù)組的遍歷,可以采用兩種方式: for 循環(huán)遍歷;each()方法遍歷
// 遍歷數(shù)組
// 1.for 循環(huán)遍歷
for (index in 0..arr.size() - 1) {
println("arr 中的元素:${arr[index]}")
}
// 2.each{} 遍歷
arr.each {
println("arr 中的數(shù)據(jù):${it}")
}
map
作為鍵值對的 map 結(jié)構(gòu),定義起來其實(shí)跟數(shù)組定義差不多..直接看代碼即可
def map1 = ["key1": "value1", "key2": "value2"]
map 中提供了 each
方法方便于遍歷
// 遍歷 map
map.each { k, v ->
println("map: key = $k value = $v")
}
IO
// IO 操作
def file = new File("../file.txt")
file.eachLine {line, lineNo->
println "lineNo=$lineNo $line"
}
方法
Groovy 中的方法,定義跟java 中沒啥區(qū)別,但是它有自己的一些特性.
括號可以省略
正常方法的寫法如下:
// 定義方法
def method1(param1, param2) {
println("param1 = $param1, param2 = $param2")
}
// 調(diào)用方法
method1(1, 2) // 輸出:param1 = 1, param2 = 2
在 Groovy 中可以直接這么調(diào)用
method1 5, 6 // 輸出: param1 = 5, param2 = 6
可見可以直接省略掉括號直接進(jìn)行方法的調(diào)用.
return 可以省略
如果省略掉 return 語句,那么 Groovy 中會(huì)默認(rèn)將最后一行當(dāng)做 return 語句的返回值
下邊兩個(gè)方法的作用一樣
def returnMethod(int param) {
return 100 * param
}
def returnMethod(int param) {
100 * param
}
類-JavaBean
在 java 中定義 Bean,我們需要提供 set/get 方法,但是在 Groovy 中,完全沒必要,直接使用就行,有點(diǎn)類似于 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還是有點(diǎn)不同的.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
循環(huán)邏輯
Groovy 中的循環(huán)邏輯,包含對范圍的 for 循環(huán);
對范圍的 for 循環(huán)
def sum = 0
for (i in 0..10) {
sum += i
}
println("sum = $sum") // sum == 55
對 List 循環(huán)
def list1 = [1, 2, 3, 4, 5, 6]
for (i in list1) {
println(i)
}
對 map 循環(huán)
比 java 中遍歷 map 方便多多多了...
def map1 = ["key1": "value1", "key2": "value2"]
for (i in map1) {
println("遍歷 map: key = ${i.key} value = ${i.value}")
}
閉包
閉包就是一段代碼塊.
有點(diǎn)類似 kotlin 中高階函數(shù)
可以將閉包當(dāng)做參數(shù)傳入方法中去,也可以賦值給變量,然后通過call
方法調(diào)用閉包,kotlin 中是使用的invoke
方法調(diào)用
如下定義一個(gè)最簡單的閉包:
def b1 = {
println "Hello Closure"
} // 定義一個(gè)閉包 b1
b1.call() // 輸出:Hello Closure
定義有參數(shù)的閉包:
// 有參數(shù)的閉包
def b2 = { key, value ->
println "key = $key, value = $value"
}
b2.call("id", 123) // 輸出:key = id, value = 123
有返回參數(shù)的閉包:
// 有參數(shù)&返回值的閉包
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
閉包關(guān)鍵變量(this、owner、delegate)
def b3 = {
println "this:$this"
println "owner:$owner"
println "delegate:$delegate"
}
b3.call()
// 打印結(jié)果:
//this:ideaGroovyConsole@1b919693
//owner:ideaGroovyConsole@1b919693
//delegate:ideaGroovyConsole@1b919693
通過 LOG 可以看到,this,owner,delegate 返回的日志都是一致的.有貓膩...
- this: 這個(gè)關(guān)鍵字同 java 中的 this,表示當(dāng)前類的方法或者變量,在 Groovy 中表示的是閉包定義處的類
- owner: 表示的是閉包定以處的類或者對象
- delegate:表示任意對象,默認(rèn)與 owner 一致
進(jìn)階
數(shù)據(jù)結(jié)構(gòu)-列表
列表的定義
在Java中我們定義一個(gè)列表一般是這樣定義的List list = new ArrayList() 或者 new LinkedList()等等.
在我們Groovy中定義一個(gè)列表只需要讓它等于[]
即可,也就是def list = []
,我們想要往里面添加元素直接往方括號里面加,用逗號隔開就行,比如def list = [1, 2, 3],這里呢會(huì)有同學(xué)有疑問,這個(gè)明明就是Java中的數(shù)組嘛,為什么到這里就變成List了呢?這個(gè)List是ArrayList還是LinkedList呢?別著急,我們打印下它的類型
def list = [1, 2, 3]
println list.class // 輸出:class java.util.ArrayList
通過輸出可以看到,此種定義方式的格式默認(rèn)是 ArrayList 的,那么我們該怎么定義一個(gè)數(shù)組呢?很簡單,可以直接使用as
進(jìn)行強(qiáng)轉(zhuǎn),或者使用強(qiáng)類型定義
// 定義數(shù)組的兩種方式:
// 第一種:使用[as]關(guān)鍵字,將 List 強(qiáng)轉(zhuǎn)成數(shù)組
def arr1 = [1, 2, 3] as int[]
// 第二種:使用強(qiáng)類型直接定義
int[] arr2 = [1, 2, 3]
println arr1.class // 輸出:class [I
println arr2.class // 輸出:class [I
同理,我要想實(shí)例化一個(gè) LikedList,那么也可以參考數(shù)組的定義方式來實(shí)現(xiàn),采用兩種方式來定義:
// 定義一個(gè) 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) //在最后添加一個(gè)元素
addList.add(0, 0) // 在指定位置添加元素
println addList // [0, 1, 2, 3, 4]
2.leftShift() 或者 <<
使用leftShift或者<<方法,表示在集合的最后添加一個(gè)元素,leftshift()的重載運(yùn)算符是<<
// 增加-leftShift
addList.leftShift(5)
addList << 6
println addList // [0, 1, 2, 3, 4, 5, 6]
3.直接使用 +
還可以直接使用+
號進(jìn)行拼接
// 增加-直接使用加號
addList = addList + 7
println addList // [0, 1, 2, 3, 4, 5, 6, 7]
刪除
1.remove()
類似 java,直接使用remove(Object o)
或者remove(int index)
進(jìn)行刪除,其他的還有removeAll()
,removeElement()
類似,可自查
def deleteList = ["A", "B", "C"]
// 刪除-使用 remove
deleteList.remove("C") // 輸出:[A, B]
deleteList.remove(0) // 輸出:[B]
deleteList.removeAt(0) // 內(nèi)部實(shí)際調(diào)用了上邊的 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 "第二個(gè)元素是:${searchList.get(2 - 1)}" // 第二個(gè)元素是:2
println "第三個(gè)元素是:${searchList[3 - 1]}" // 第二個(gè)元素是:3
2.find(Closure closure)
返回符合閉包內(nèi)條件的第一個(gè)元素
//查找-find 返回第一個(gè)符合條件的元素
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()
只要集合中有一個(gè)符合條件的,就返回 true
//查找-any: 只要有符合條件的就返回
println searchList.any { it ->
(it % 3) == 0
} // true
5.every(Closure closure)
every()
只有當(dāng)所有的元素都符合條件時(shí),才返回 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()
返回符合條件的元素的個(gè)數(shù)
// 查找-count:返回符合條件的元素的個(gè)數(shù)
def count = searchList.count { it ->
(it % 2) == 0
}
println "對 2 取余為 0 的個(gè)數(shù)為:$count" // 2個(gè)
數(shù)據(jù)結(jié)構(gòu)-映射
映射的定義
其實(shí)就是 java 中的 Map 操作.
在 java 中我們這么定義 Map:Map map = new HashMap()
, 在 Groovy 中的定義方式跟集合差不多,集合中是單元素的,映射是鍵值對形式的,也就是每個(gè)元素都是key:value
的形式.
def defMap = ["name": "Tom", "age": 18, "man": true]
println defMap // [name:Tom, age:18, man:true]
類似集合,我們打印一下這個(gè) Map 是哪種類型的?
println defMap.getClass() // class java.util.LinkedHashMap
所以,如果你想定義別的 Map 類型,可以采用等同于集合的處理方式:第一種通過as
關(guān)鍵字進(jìn)行強(qiáng)轉(zhuǎn);第二種通過強(qiáng)類型定義來定義
映射的常見操作
1.添加元素
添加元素有put()
方法,以及中括號直接操作,點(diǎn)操作;添加多個(gè)用putAll()
假如新添加的元素不存在,那么就直接添加;如果已經(jīng)存在了,那么就會(huì)替換對應(yīng)的 value
// 添加元素
defMap.put("height", 100)
defMap["birthday"] = "2011-11-11"
defMap.father = "Jack"
// 此時(shí)輸出:[name:Tom, age:18, man:true, money:200.56, height:100, birthday:2011-11-11, father:Jack]
2.刪除元素
針對刪除元素,目前常用的就是remove()
方法
// 刪除元素
defMap.remove("birthday")
3.根據(jù)key 獲取 value
通過 key 獲取 value ,Groovy 有提供get()
,getAt()
方法,同時(shí)也提供了方便的操作符獲取,比如直接.
或者[]
來獲取
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.遍歷
遍歷主要用到兩個(gè)方法:each()
和eachWithIndex()
,第二個(gè)方法會(huì)附帶輸出當(dāng)前索引值.
// 遍歷
defMap.each {
println "key=${it.key}, value=${it.value}"
}
defMap.eachWithIndex { Map.Entry<String, Serializable> 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()
數(shù)據(jù)結(jié)構(gòu)-范圍
在 Groovy 中,有個(gè) 范圍
的數(shù)據(jù)結(jié)構(gòu),其實(shí)也很簡單,比如要定義一個(gè) 1 到 10 的范圍,就直接def a = 1..10
就行了, 主要用到了..
操作符.
其實(shí)所謂的范圍,本質(zhì)上是一個(gè) List.
// 定義一個(gè)范圍
def rangeInt = 1..10 // class groovy.lang.IntRange
def rangeString = "A".."D" //class groovy.lang.ObjectRange
常用操作
1.獲取范圍中某個(gè)值
// 獲取范圍中某個(gè)值
println rangeInt.get(1) // 索引值為 1 的數(shù)字是 2
println rangeInt[1]
2.范圍中是否包含某個(gè)值
// 范圍中是否包含某個(gè)值
println rangeInt.contains(4) // 存在則返回 true
3.獲取范圍第一個(gè)/最后一值
在范圍的類定義中,有兩個(gè)屬性:from
,to
,對應(yīng)的就是當(dāng)前范圍的第一個(gè)和最后一個(gè)值.
// 獲取范圍的第一個(gè)值
println rangeInt.from // 1
// 獲取范圍最后一個(gè)值
println rangeInt.to // 10
4.遍歷
// 遍歷
rangeInt.each {
println it
}