Groovy是什么
Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy 可以使用其他 Java 语言编写的库(百度百科)。
把Groovy看做是敏捷开发语言,主要因为它不像Java语言有那么多严格的规范。如果使用过类似JavaScript这种脚本语言,会更容易明白它的语法。Groovy也是面向对象的编程语言,但是它也可以用作纯粹的脚本语言。使用该语言我们不必编写过多的代码,同时又具有闭包和动态语言的特性。
下面四种方式都会输出“hello world”,而且是不需要放在main方法中就可以执行,当然了放在main中也可以执行。
System.out.println("hello world");
System.out.println"hello world";
println("hello world")
println"hello world"
看到上面这几行代码,可能就有人对它嗤之以鼻了,特别是对代码有洁癖的人,上面代码算什么,有时候加括号而且行末分号可有可无。你可以痛斥它语法上的不规范,但是不可否定它语法上的简洁性,语法上的不规范侧面上体现出这门语言的灵活性。
Groovy是基于JVM的语言,所以它可以与Java无缝对接。Groovy可以集成所有已经存在的Java对象和类库,且可以直接编译成Java字节码,这样可以在任何使用Java的地方使用Groovy。类似地,用标准 Java 代码编写的内容也可以在 Groovy 中重用。
Groovy编写的文件扩展名是.groovy,学习Groovy官网是groovy-lang.org,当然了做Android开发的人员可以直接用Gradle构建工具来运行Groovy,这时候扩展名是.gradle。
为什么要学习Groovy
为什么要学习Groovy,简单来说就是Groovy可以用较少的代码实现较多的功能。
- Groovy 的松散的Java 语法允许省略分号和修改符。
- 除非另行指定,Groovy 的所有内容都为 public。
- Groovy 允许定义简单脚本,同时无需定义正规的 class 对象。
- Groovy 在普通的常用 Java 对象上增加了一些独特的方法和快捷方式,使得它们更容易使用。
- 变量,属性,方法,闭包的参数以及方法的返回类型都是可有可无的。
- Groovy 默认导入常用的包。
Groovy的生态圈已经很全面了。
- Gradle,自动化构建工具,通过编写简单的Groovy脚本,便可进行依赖管理和项目构建。如果你想使用Android Studio进行Android开发,Gradle已经成为了Android Studio中的默认构建工具了。
- Grails,一套用于快速Web应用开发的开源框架,它基于Groovy编程语言,并构建于Spring、Hibernate和其它标准Java框架之上,从而为大家带来一套能实现超高生产力的一站式框架。
- Spock,测试框架,可通过其特有的DSL编写测试案例;
- Griffon,Swing开发框架,其灵感来自于Grails。
Groovy是一个面向对象的脚本语言,跟Java还是有很大不同的,多了解一门语言,对于提高自己的综合编程能力也是大有裨益的。另外,如果你是一名Java软件工程师,学习Groovy几乎可以说是零成本的。既然有这么多好处,确实是时候来学习一下Groovy了。
Groovy注释
与Java的注释语法相同,如://注释 /* 注释 */ /** 注释 */ 都支持,唯一不同的是,Groovy支持像Shell脚本那样的首行附加注释
#!/usr/bin/env groovy
defx=1
...
“#!”注释只允许在脚本文件的第一行出现,通过这种方式 Unix shell能定位groovy 的启动脚本并且运行这些脚本。
Groovy变量
Groovy中定义变量默认的修饰符是public,变量定义时遵循Java变量命名规范,变量名以字母、下划线或美元符号$开始,可以包含字母、数字、下划线和美元符号$,但关键字除外。除了这些规则之外,Groovy定义变量时如果是一行定义一个类型,末尾的分号可以省略,但是如果多个变量占一行,变量之间必须以分号分割。
整形变量
整数类型与Java相同:byte、char、short、int、long、java.lang.BigInteger。
//基本数据类型
bytea=1
charb=2
shortc=3
intd=4
longe=5
intx=9;
intm=10;longn=11
//大整型
BigInteger bi=6
在Groovy中,上面的变量定义方式跟Java可以说没有太大的不同,但是Groovy中多了一个关键字def来定义变量。包括下面介绍的String类型的变量都可以使用def来定义。用def定义的变量时无类型的变量,这里所说的无类型的变量,并不表示该变量就不属于某一个类型了,def修饰变量正是Groovy为动态语言的标记,大概def修饰变量就相当于Java中Object来修饰变量吧。
如果通过使用def关键字使用可选类型,那么整数的类型将是可变的:它取决于这个类型实际包含的值。
defa=1
assertainstanceofInteger
//assert a instanceof Long//错误
defb=2147483648
assertbinstanceofLong
boolean变量的定义与整形类似,这里就不再介绍了。
字符变量
与Java不同,Groovy没有显式的字符文本,然而你可以通过三种不同方式,可以将Groovy字符串实际作为一个字符使用。
charc1='A'//(1)
assertc1 instanceofCharacter
def c2='B'aschar//(2)
assertc2 instanceofCharacter
def c3=(char)'C'//(3)
assertc3 instanceofCharacter
- 当定义变量时,通过指定char类型,使变量包含字符
- 通过as操作符使用类型强制转换
- 通过char操作符做类型转换
(1)定义时使用的是char类型直接限定的,而(2)(3)定义使用的是无类型def定义的。
字符串
字符串定义中,除了支持Java语法定义字符串,还提供了其它方式定义字符串,如单引号、三单引号、三双引号和插值字符串等。
def str="hello world"
def str01='hello world'
def str02='''hello world'''
def str03='hello'+'world'
def str04="""hello world"""
三单引号和三双引号字符串是多行的,你可以使字符串内容跨越行边界,不需要将字符串分割为一些片段,不需要连接,或换行转义符:
def multilineString='''line one
line two
line three'''
如果你的代码是缩进的,如类中的方法体,字符串将包括缩进的空格。转义字符的使用与Java相同。
'an escaped single quote: \' needs a backslash'
'an escaped escape character: \\ needs a double backslash'
插值字符串
任何Groovy表达式可以在所有字符文本进行插值,除了单引号和三单引号字符串。插值是使用占位符上的字符串计算值替换占位符的操作。占位符表达式是被${}包围,或前缀为$的表达式。
为$的表达式。
def name="admin"
def str="hello ${name}"
而且任何Groovy表达式是合法的,如下使用都是合法的。
def str="1 + 2 = ${1 + 2}"
assertstr=="1 + 2 = 3"
不仅任何表达式,实际上也允许${}占位符。语句也是被允许的,但一个语句等效于null。如果有多个语句插入占位符,那么最后一个语句应该返回一个有意义的值被插入占位符。例如,"The sum of 1 and 2 is equal to ${def a = 1; def b = 2; a + b}"字符串是被支持的,也能如预期一样工作,但一个好的实践是在GString占位符插入一个简单的表达式。
斜杠字符串
这里斜杠字符串跟JavaScript中斜杠字符串使用方式类似,使用/定义字符串,主要用于定义正则表达式和模式,这种方式在定义正则表达式的时候相当有用,因为在斜杠中包括的字符串不需要转义字符。
//Java中定义正则表达式
Stringregex="//.*hello world.*//";
//Groovy定义正则表达式
def regex=/.*hello world.*/
可以用正斜杠定义字符串,但是如果字符串本身就包含正斜杠,这时候就需要转义了。
def escapeSlash=/The character\/isaforward slash/
assertescapeSlash=='The character / is a forward slash'
同样斜杠字符串也是多行的并且支持插值。
def name="admin"
def str=/hello${name}/
字符串总结表
| 类型 | 表示方式 | 插值 | 多行 | 转义字符 |
|---|---|---|---|---|
| 单引号 | '...' |
否 | 否 | \ |
| 三单引号 | '''...''' |
否 | 是 | \ |
| 双引号 | "..." |
是 | 否 | \ |
| 三双引号 | """...""" |
是 | 是 | \ |
| 斜杠 | /.../ |
是 | 是 | \ |
数组
Groovy使用中括号[]来对数组进行初始化赋值,但是不持之Java中用大括号{}进行赋值,大括号在Groovy中会被认为是闭包的标记,闭包在下一篇文章中再做介绍。
//该种方式不支持
//String[] strs={"aaa","bbb","ccc"}
String[]array=["aaa","bbb","ccc"]
assertarrayinstanceofString[]
//创建字面量数组,需要通过类型转换或类型定义来定义数组类型。
def numAry=[1,2,3]asint[]
assertnumAry instanceofint[]
assertnumAry.size()==3
//创建包含不同类型的数组
String[]mulAry=["aaa",123,true]
//定义多维数组 指定数组为3*3
def matrix3=newInteger[3][3]
assertmatrix3.size()==3
//不指定数组大小
Integer[][]matrix2
matrix2=[[1,2],[3,4]]
assertmatrix2 instanceofInteger[][]
List列表
定义列表与数组不同之处在于在变量声明时不需要[],Groovy的列表是java.util.List,因为Groovy没有定义任何集合类。当定义一个列表常量时,默认的列表具体实现是java.util.ArrayList,除非你指定。
请大家注意,List定义时如果是通过字面量形式定义的,不可指定声明类型是int或者String,但是可以使用List、ArrayList或者LinkedList。
//正确
def nums01=[1,2,3]
assertnums01 instanceofList
assertnums01.size()==3
//错误
//int num02=[1,2,3]
//创建包含不同类型列表
def myList=["aaa",123,true]
List list=[1,2,3]
LinkedList list01=[1,2,3]
def list02=[1,2,3]asLinkedList
访问列表如访问数组类似,通过中括号[索引]的形式访问,但是索引可以为负值,负值从末尾往前,最后一个索引为-1。也可以使用范围[m..n]或者左移运算符
def list=[1,2,3,4]
assertlist[0]==1
assertlist[1]==2;
assertlist[-1]==4
assertlist[-2]==3
list[1]=100
assertlist[1]==100
list[4]=101
assertlist[4]==101
list<<102//此处是列表左移
assertlist[5]==102
assertlist[-1]==102
assertlist[0,2]==[1,3]
assertlist[0..2]==[1,100,3]
Map集合
在Groovy中称为映射,映射使键到值关联,使用冒号将键值分隔开,每个键值对使用逗号,整个键和值使用方括号包围。默认的映射实际上是java.util.LinkedHashMap类型的。
def maps=[one:100,two:101,three:102]
assertmaps['one']==100
assertmaps.one==100
maps['two']=1001
assertmaps['two']==1001
assertmaps instanceofjava.util.LinkedHashMap
在上述定义中one、two、three默认是字符串,所以当我们尝试使用maps[one]访问时会出错,但是如果所有的键都是统一并且可以转换为非String类型,这时候可以根据类型访问。
def maps=[1:100,2:101,3:102]
assertmaps[1]==100
//assert maps.1==100;//报错
在映射中键可以使用一个变量作为值,但是要注意必须加上圆括号包围这个变量或者表达式。
def key="name"
def person=[key:'admin']
assert!person.containsKey('name')
assertperson.containsKey('key')
//////////////////////////////////////////////////
def key="name"
def person=[(key):'admin']
assertperson.containsKey('name')
assert!person.containsKey('key')
接下来我们总结一下,如果定义一个空的数组、列表或者映射是什么样子的。
//字符串
String[]emptyStrs=[]
//或
def nums=[]asint[]
//列表
def emptyList=[]
//映射
def emptyMap=[:]
本篇文章主要介绍了Groovy的语法和变量的定义,有关函数和类可以参看下一篇文章Groovy进阶之函数、闭包和类。