Gradle 系列之一: Groovy 语法基础

[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
}

你可能感兴趣的:(Gradle 系列之一: Groovy 语法基础)