字符串
引号
Groovy支持单引号(’’),双引号(””)和三引号(” “ “)来封装字符串。其中三引号表示的字符串可以包含多行文本。
1 | def a = """Spread |
输出结果如下:
1 | Spread |
使用单引号封装的字符串的值就是所列出的字符序列本身,另外两种形式的字符串的值可能会进一步被解释,任何包含在解释型字符串中的${expression}都将被求值,其结果是字符串的一部分。
1 | def age = 25 |
Groovy的通用原则是只在字符串需要被解释的时候使用双引号,其他情况下使用单引号。Groovy中也使用字符反斜线\来进行转义。
###正则表达式
Groovy支持使用~”regex”来定义正则表达式,通过下面的方法可以创建一个正则表达式:
1 | def regex =~ 'cheese' |
在if语句或者while语句中,当Groovy操作符”=~”作为一个谓词出现时,左边的操作数String对象将和右边的正则表达式匹配。下面所有的表达式结果均为true:
1 | def regex =~ 'cheese' |
“==~”是精确匹配符。
在正则表达式中,脱字符号(^)和美元符号($)分别表示某行的开始和结尾。
1 | def rhyme = 'a b c' |
加号(+)表示在表达式中位于它前面的字符出现一次或者多次,星号(*)表示出现零次或者多次。”{“和 “}”用来匹配位于”{“之前指定次数的字符,下列表达式的结果均为true:
1 | 'aaaaab' =~ 'a * b' |
列表和映射
列表
索引
列表是一种用来储存数据项集合的数据结构。在Groovy中,列表字面值是一系列包含在方括号中的对象集合,这些对象用逗号分隔。
Groovy列表使用索引操作符[]来标识元素值。列表的索引从0开始,指向列表的第一个元素。
1 | def numbers = [11, 12, 13, 14] // 列表含有四个元素 |
如果整形索引为负数,则其引用的元素从列表末端开始向前移动。
1 | numbers[-1] // 值为14 |
索引段同样可以用于列表。
1 | [11, 12, 13, 14][2] // 值为13 |
也可以通过索引范围来操作列表。
1 | numbers[0..2] // 返回列表[11, 12, 13] |
操作符
主要使用以下操作符对列表进行操作。
- <<
- +
- -
1 | def a = [1] |
映射
映射(也就是大家熟知的组合数组,词典,表格和散列)是一种引用对象的无需集合。映射中的所有元素都可以通过关键字访问,它使用的关键字可以是任意类型的。
在映射字面值中,如果某个元素的关键字是一个变量名,那么它将被解释成一个String。
1 | def x = 1 |
于是,m就是映射:
m = [‘x’ : 2, ‘y’ : 1]
范围
范围是表达特定序列值的一种简略方法。它通过序列中第一个值和最后一个值表示,范围还具有包含和不包含关系。
1 | 1900..1999 // 包含边界 |
包含边界的范围通过..表示,而不包含边界的范围通过..<。
Groovy也为范围定义了一些方法。
- get
- getFrom (获取当前范围中下标最小的元素值)
- getTo (获取当前范围中下标最大的元素值)
- isReverse
- size
- subList
1 | def twentiethCentury = 1900..1999 |
流程控制
Groovy提供了一些用来改变程序逻辑的流程控制语句,可以将它们分为三种流程控制结构:
- 顺序
- 选择
- 迭代
while语句
最基本的迭代子句是while语句。
for语句
for语句用于循环处理某个范围内,集合(列表,映射或者数组)或者字符串。
if语句
if语句大家应该都很熟悉,此处不再赘述。
switch语句
一连串频繁出现的if-else语句,可以通过一个switch语句来实现。
Switch和范围
case表达式即可以表示某个整型值,也可以表示整型值的范围。
1 | import console.* |
输出结果为:
Enter examination score: 50
Score: 50; grade: C
break语句
break语句通常用来改变循环语句和switch语句中的控制流程。在循环结构体内执行break语句时,将立即终止循环体的最内层循环。
continue语句
continue语句是break语句的补充,仅限于在while和for循环中使用。
当执行continue语句时,将结束本次循环,并跳转到离它最近的条件判断语句,以确认是否执行下一个循环。
在含有continue语句的循环中,程序将跳过循环体内下面所有尚未执行的语句。
闭包
闭包的调用
1 | def clos = {println 'Hello world'} |
这段代码的含义是使用标识符clos引用这个闭包,使用call来执行这个标识符所引用的代码块。
在闭包声明中引入形参。
1 | def clos = {param -> println "Hello ${param}"} |
输出结果为:
Hello world
Hello again
Hello shortcut
在第三个语句中我们会可以看到,call是可以省略的。
闭包,集合和字符串
许多列表,映射和字符串方法都接受闭包参数。
each方法和闭包
each方法的原型为void each(Closure closure),它常用于列表,映射和字符串,以遍历每个元素,并将闭包应用于每个元素。
1 | [1, 2, 3, 4].each {println it} |
其输出结果为:
1
2
3
4
5
find方法和闭包
find方法返回集合中符合某个判断标准的第一个值。在闭包中,集合元素使用的判断条件必须是布尔表达式。当存在符合条件的值时,find方法将返回第一个符合条件的值,否则,返回null。
1 | def value = [1, 3, 5, 7, 9].find{element -> element > 6} |
输出结果为:
Found:7
findAll方法将遍历所有元素,并返回一个符合条件的列表。
1 | def values = [1, 3, 5, 7, 9].findAll{element -> element > 6} |
输出结果为:
7
9
collect方法和闭包
collect将遍历某个集合,并使用闭包里的变换方法,将集合中的每个元素转换为一个新值。
collect简单示例:
1 | def list = [1, 2, 3, 4].collect{element -> return element * element} |
输出结果为:
list:[1, 4, 9, 16]
collect高级示例:
1 | def doubles = {item -> 2 * item} |
输出结果为:
Doubling:[2, 4, 6, 8]
inject方法和闭包
inject方法可用于遍历集合。
inject简单示例:
1 | def factorial = [2, 3, 4, 5].inject(1){previous, element -> previous * element} |
输出结果为:
Factorial(5):120
类
类的实例
无构造器
下面简单介绍Groovy中的类,基本上和Java里的类是一样的。
一个简单的Groovy类
1 | class People{ |
这样就定义了一个People类,使用new关键字进行实例化(和Java一样)。
另外说明一点,p.name
所示的属性引用方法实际上是通过p.getName()实现的。
自定义构造器
上面介绍的是没有构造器的情况,所以实例化的时候使用的是默认构造器。现在为People增加一个构造器方法,代码如下:
1 | class People{ |
此时若想实例化一个People类,只有使用def p = new People('张三', 20)
这种方式,如果使用之前的方式来实例化,系统会提示报错,这是因为当类包含一个用户自定义的构造器后,程序并不会自动生成默认的构造器。
类的继承,抽象类和接口类
Groovy中类的继承,抽象类和接口类的概念和Java基本一样,此处不再赘述。
总结
Groovy语言的语法是基于Java的,它包含了许多Python,Ruby和Smalltalk的语言特性。Groovy语言编写的应用程序完全可以使用Java API,它与使用Java编写的框架和组件实现无缝连接。
Groovy2.4开始支持Android开发,但就目前看来,支持的工具非常少,与Scala相比还差得远。因为Groovy是动态语言,在Android上性能可能存在问题。
在这篇博客中,作者对Android的备选开发语言里面做了一个调研,这个文档有比较Groovy,Clojure,Sacla和Kotlin的各种优劣势,最终作者倾向于使用kotlin。
在线API doc:http://www.groovy-lang.org/api.html