学习Groovy的特性
翻译自 http://sysgears.com/articles/groovy-differences-java/
Groovy基于jvm,是一种面向对象的动态语言。如果你需要编写轻量级的脚本并且想要从Java的生态环境中获益,那么Groovy对于你来说是再合适不过的候选者。Groovy动态得被编译成字节码,并且兼容大部分的Java类库。同时Groovy非常易于学习,因为在Groovy中Java的语法都是有效的。但还是有些注意事项需要你在开始编程之前了解的。这篇文章展现了Groovy的一些特性并提供了一些帮助你编写清晰,groovy-style代码的建议。
Groovy beans
声明Groovy beans是非常简单的。典型的Java bean需要包含构造方法,私有属性和getter / setter 方法。Groovy bean仅仅需要field,getter / setter 方法会被隐式得创建。
class User { String firstName // bean field String lastName // bean field } def user = new User() user.firstName = "John" user.lastName = "Doe"
user.firstName和user.lastName会调用setter方法完成任务。如果有必要的话你也可以为field声明自定义getter / setter 方法。下面举个例子:
class User { String firstName String getFirstName() { "The first name is $firstName" } void setFirstName(String firstName) { this.firstName = "[$firstName]" } // ... } user.firstName = 'John' println user.firstName
{}中的内容通过setter方法添加,"the first name"后面通过getter方法得到。结果是这样:
The first name is [John]
如果为field设置了访问修饰符,那就仅仅创建了field,getter / setter方法不会被自动创建。
Groovy 闭包
Groovy提供了一种创建方法为一等对象的方式————Groovy 闭包。使用闭包,你能够定义代码块并且传递参数,就像它是常规变量一样。
// the simplest closure def hello = {"Hello, $it!"} assert hello('Chris') == 'Hello, Chris!' // the closure that do not take any params def bye = {->'Bye!'} assert bye() == 'Bye!' // the closure with several params def niceHello = {firstName, lastName -> "Hello, $firstName $lastName!"} assert niceHello('Chris', 'Bennett') == 'Hello, Chris Bennett!'
如上所示,闭包默认持有一个it参数,你可以指定可命名的参数改变这一默认行为。或者声明{-> ...}省略参数。
Groovy list和map
Groovy 为lists和Maps提供了内建的支持,并且允许用类似于JavaScript的方式初始化和操作数据结构。首先,让我们看一眼List的实现,我们可以只用两个[]创建一个空的List。
// an empty list def emptyList = [] // predefined list def list = ['One', 'Two', 'Three']
或者从List中取出一个或多个元素。
def list = ['One', 'Two', 'Three'] // gets the first element from the list assert list[0] == 'One' // gets a range of elements from the list assert list[1..2] == ['Two', 'Three'] // gets another range assert list[-1..-2] == ['Three', 'Two']
另外为迭代和转化lists提供了一系列可用的便捷操作:
// iterates the list def emptyList = [] list.each {emptyList << "$it!"} assert emptyList == ['3!', '1!', '2!'] // iterates the list and transforms each entry into a new value // using the closure assert list.collect {it * 2} == [6, 2, 4] // sorts using the closure as a comparator assert list.sort {it1, it2 -> it1 <=> it2} == [1, 2, 3] // gets min or max using closure as comparator assert list.min {it1, it2 -> it1 <=> it2} == 1
Map的实现也有很多的语法糖。可以通过[]和:声明一个空的map:
// an empty map def emptyMap = [:] // predefined map def map = [John: 10, Mark: 20, Peter: 'Not defined']
两种风格获取Map的值————bean风格或者数组风格
def map = [John: 10, Mark: 20, Peter: 'Not defined'] // the array style assert map['Peter'] == 'Not defined' // the bean style assert map.Mark == 20 // also you can preset default value that will be returned by // the get method if key does not exist assert map.get('Michael', 100) == 100
借助闭包实现迭代和转换:
// iterates the map def emptyMap = [:] def map = [John: 10, Mark: 20, Peter: 'Not defined'] map.each { key, value -> emptyMap.put key, "$key: $value" as String } assert emptyMap == [John: 'John: 10', Mark: 'Mark: 20', Peter: 'Peter: Not defined'] // iterates the map and transforms each entry using // the closure, returns a list of transformed values assert map.collect { key, value -> "$key: $value" } == ['John: 10', 'Mark: 20', 'Peter: Not defined'] // sorts map elements using the closure as a comparator map.put 'Chris', 15 assert map.sort { e1, e2 -> e1.key <=> e2.key } == [John: 10, Chris: 15, Mark: 20, Peter: 'Not defined']
其他有用的
-
boolean操作符==和Java中的equals相同效果,并且不区分类型。不像Java中==意味着基本类型相等和对象地址相等。如果你要比较对象的地址,使用is方法:
assert [] == [] assert ![].is([])
-
.*操作符被引入用于表示在集合内所有的成员上执行操作:
assert [1, 2, 3] == ['a', 'ab', 'abc']*.size()
-
在方法的末端return是可选的:
def foo() { // do something return something } // is equals to def bar() { // do something something }
结语
Groovy还有很多有趣的特性:元编程,函数式编程,AST转换。在学习的路途上你一定会发现它们。Groovy的强大之处在于,你可以用基本的Java语法开始,然后逐步学习并且改进代码直到它们真正意义上的灵活和动态。