Groovy 语言快速入门
Groovy 简介
Groovy 是 Apache 旗下的一门基于 JVM 平台的动态编程语言,在语言的设计上 Groovy 吸纳了 Python、Ruby 和 Smalltalk 语言的优秀特性,语法非常简练和优美,开发效率也非常高。Groovy 可以与 Java 语言无缝对接,Groovy 脚本里可以写 Java 代码,也可以在 Java 程序里调用 Groovy 脚本,两者的无缝衔接有效地降低了 Java 开发者学习 Groovy 的成本。Groovy 代码能够与Java 代码很好地结合,Groovy 支持99%的 Java 语法,但是 Groovy 并不会替代 Java,而是相辅相成、互补的关系,具体使用哪门语言这取决于要解决的问题和使用的场景。
Groovy 是 用于 Java 虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同时又具有闭包和动态语言中的其他特性。在Java中要输出"hello world"需要像下面这样,创建一个类,然后创建一个main方法:
public class Hello {
public static void main(String[] args) {
System.out.println("hello world");
}
}
在Groovy中,这些都可以省略,下面这4种方式都可以输出“hello world”。
System.out.println("hello world");
System.out.println "hello world";
println("hello world")
println 'hello world'
如果 Groovy 脚本文件里只有执行代码,没有类的定义,则 Groovy 编译器会生成一个 Script 的子类,类名和脚本文件的文件名一样,而脚本中的代码会被包含在一个名为run的方法中,同时还会生成一个main方法,作为整个脚本的入口。所以,作为 JVM 平台语言,与 Java 本质上还是一样的。
下面介绍一下一些通用的Groovy语法。
1、不需要分号
学过C/C++/java的同学都会对分号很熟悉,我们使用的如此频繁,几乎放在每一行的末尾,然而在Groovy中分号是可选的,你可以省略他们。
2、return关键字可省略
在 Groovy 中,方法的最后一句表达式可作为返回值返回,而不需要return关键字。
String sayHello() { return "hello world!" }
String sayHello() { "hello world!" }
3、def 和 类型
作为动态语言,Groovy 中所有的变量都是对象,所有对象继承自java.lang.Object。在声明一个变量时,Groovy 不要求强制类型声明,仅仅要求变量名前使用关键字 def(在 Groovy 1 以前的版本中,甚至连 def 都不需要)。
def var="hello world"
println var
println var.class
由此可以看到程序最后输出了var的实际类型为:java.lang.String
备注:作为例外,方法参数和循环变量的声明不需要def。
4、数组初始化语法
在 Groovy 中,{...} 语句块是留给闭包(Closure)使用的,所以不能像 Java 中一样使用下面这种方式初始化数组:
int[] array = { 1, 2, 3}
而应该是下面这样
int[] array = [1,2,3]
5、Getters and Setters
Groovy 默认会隐式的创建getter、setter方法,并且会提供带参的构造器,下面两者是等价的。
// In Java
public class Person {
private String name;
Person(String name) {
this.name = name
}
public String getName() {
return name
}
public void setName(String name) {
this.name = name
}
}
// In Groovy
class Person {
String name
}
def person = new Person(name: '张三')
assert '张三' == person.name
person.name = '李四'
//person.setName('李四')
assert '李四' == person.getName()
备注:当你对getter/setter方法有特殊要求,你尽可提供自己的方法,Groovy默认的getter/setter方法会被替换。
6、包访问权限
在 Java 中如果没有显式的指定访问修饰符(public、protected、private)那么默认是包访问权限,但在 Groovy 中默认是public的,所以需要使用@PackageScope注解。
class Person {
@PackageScope String name
}
7、使用命名的参数初始化Bean
class Student {
String name
int age
}
初始化一个实例的时候你可能会这样写:
def student = new Student()
student.name = "Tom"
student.age = 20
其实你可以用带命名的参数的默认构造器,会大大减少代码量:
def student = new Student(name: "Tom", age: 20)
8、使用with()来重复某一个操作
当更新一个实例的时候,你可以使用with()来省略相同的前缀,在Java中你必须这样写:
server.name = application.name
server.status = status
server.sessionCount = 3
server.start()
server.stop()
Groovy中则可以使用with():
server.with {
name = application.name
status = status
sessionCount = 3
start()
stop()
}
9、Equals 和 ==
Java里的==等同于Groovy里的is()方法,Groovy中的==是更智能的equals(),比较两个类的时候,你应该使用a.is(b),而不是==。Groovy中的==可以自动避免NullPointerException异常,如下所示:
替换
status != null && status.equals(ControlConstants.STATUS_COMPLETED)
为
status == ControlConstants.STATUS_COMPLETED
10、字符串
在Groovy种有两种字符串类型,普通字符串(java.lang.String)和插值字符串(groovy.lang.GString)。
普通字符串使用单引号
println 'hello'
插值字符串使用双引号
def name = '张三'
println "hello $name"
除此之外,还支持三单引号的写法,可以保留文本的换行及缩进格式
def lines = '''line one
line two
line three
'''
println lines
// 可以写成下面这种形式,可读性更好,\表示连字符
def lines = '''\
line one
line two
line three
'''
println lines
11、函数
Groovy 函数的返回类型可以不声明,默认返回最后一行代码的运行结果,但需要在声明函数的时候添加def关键字。反之,如果在声明函数中定义了返回值类型则可以省略def关键字,但函数中则必须使用return返回正确的数据类型。如下所示:
(1)函数定义时,参数的类型也可以不指定。例如:
//无需指定参数类型
String myFunction(arg1,arg2){
...
}
(2)除了变量定义可以不指定类型外,Groovy中函数的返回值也可以是无类型的。比如:
//无类型的函数定义,必须使用def关键字
def myFunction(){
//最后一行代码的执行结果就是本函数的返回值
last_line
}
//如果指定了函数返回类型,则可不必加def关键字来定义函数,但是必须有return。
String getString(){
return "I am a string"
}
注意,如果函数定义时候指明了返回值类型的话,函数中则必须返回正确的数据类型,否则运行时报错。如果使用了动态类型的话,你就可以返回任何类型了。
Groovy 方法的其他特性与Java一样,比如支持重载、不定长参数(...)等。
12、闭包
Groovy 提供了闭包的支持,语法和 Lambda 表达式有些类似,简单来说,闭包就是一段可执行的代码块或函数指针。闭包在 Groovy 中是groovy.lang.Closure类的实例,这使得闭包可以赋值给变量,或者作为参数传递。Groovy 定义闭包的语法很简单,就像下面这样。
//闭包的参数为可选项
def closure = { [closureParameters -> ] statements }
闭包可以访问外部变量,而方法(函数)则不能。
def str = 'hello'
def closure={
println str
}
closure()//输出hello
闭包调用的方式有两种,闭包.call(参数)或者闭包(参数),在调用的时候可以省略圆括号。
def closure = {
param -> println param
}
closure('hello')
closure.call('hello')
closure 'hello'
闭包的参数是可选的,如果没有参数的话可以省略->操作符。
def closure = {println 'hello'}
closure()
多个参数以逗号分隔,参数类型和方法一样可以显式声明也可省略,如下所示:
def closure = { String x, int y ->
println "hey ${x} the value is ${y}"
}
如果只有一个参数的话,也可省略参数的定义,Groovy提供了一个隐式的参数it来替代它。
def closure = { it -> println it }
//和上面是等价的
def closure = { println it }
closure('hello')
闭包可以作为参数传入,闭包作为方法的唯一参数或最后一个参数时可省略括号。
def eachLine(lines, closure) {
for (String line : lines) {
closure(line)
}
}
eachLine('a'..'z',{ println it })
//可省略括号,与上面等价
eachLine('a'..'z') { println it }