Gradle 系列之一: Groovy 語法基礎(chǔ)

[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

API

// 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
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,737評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內(nèi)容