summaryrefslogtreecommitdiffhomepage
path: root/zh-cn/groovy-cn.html.markdown
blob: f83dff026a9d913010639c83dff5b8602008d61d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
---
language: Groovy
filename: learngroovy-cn.groovy
contributors:
    - ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"]
translators:
    - ["Todd Gao", "http://github.com/7c00"]
lang: zh-cn
---

Groovy - Java平台的动态语言。[了解更多。](http://www.groovy-lang.org/)

```groovy
/*
  安装:

  1) 安装 GVM - http://gvmtool.net/
  2) 安装 Groovy: gvm install groovy
  3) 启动 groovy 控制台,键入: groovyConsole

*/

//  双斜线开始的是单行注释
/*
像这样的是多行注释
*/

// Hello World
println "Hello world!"

/*
  变量:

  可以给变量赋值,以便稍后使用
*/

def x = 1
println x

x = new java.util.Date()
println x

x = -3.1499392
println x

x = false
println x

x = "Groovy!"
println x

/*
  集合和映射
*/

//创建一个空的列表
def technologies = []

/*** 往列表中增加一个元素 ***/

// 和Java一样
technologies.add("Grails")

// 左移添加,返回该列表
technologies << "Groovy"

// 增加多个元素
technologies.addAll(["Gradle","Griffon"])

/*** 从列表中删除元素 ***/

// 和Java一样
technologies.remove("Griffon")

// 减号也行
technologies = technologies - 'Grails'

/*** 遍历列表 ***/

// 遍历列表中的元素
technologies.each { println "Technology: $it"}
technologies.eachWithIndex { it, i -> println "$i: $it"}

/*** 检查列表内容 ***/

//判断列表是否包含某元素,返回boolean
contained = technologies.contains( 'Groovy' )

// 或
contained = 'Groovy' in technologies

// 检查多个元素
technologies.containsAll(['Groovy','Grails'])

/*** 列表排序 ***/

// 排序列表(修改原列表)
technologies.sort()

// 要想不修改原列表,可以这样:
sortedTechnologies = technologies.sort( false )

/*** 列表操作 ***/

//替换列表元素
Collections.replaceAll(technologies, 'Gradle', 'gradle')

//打乱列表
Collections.shuffle(technologies, new Random())

//清空列表
technologies.clear()

//创建空的映射
def devMap = [:]

//增加值
devMap = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']
devMap.put('lastName','Perez')

//遍历映射元素
devMap.each { println "$it.key: $it.value" }
devMap.eachWithIndex { it, i -> println "$i: $it"}

//判断映射是否包含某键
assert devMap.containsKey('name')

//判断映射是否包含某值
assert devMap.containsValue('Roberto')

//取得映射所有的键
println devMap.keySet()

//取得映射所有的值
println devMap.values()

/*
  Groovy Beans

  GroovyBeans 是 JavaBeans,但使用了更简单的语法

  Groovy 被编译为字节码时,遵循下列规则。

    * 如果一个名字声明时带有访问修饰符(public, private, 或者 protected),
      则会生成一个字段(field)。

    * 名字声明时没有访问修饰符,则会生成一个带有public getter和setter的
      private字段,即属性(property)。

    * 如果一个属性声明为final,则会创建一个final的private字段,但不会生成setter。

    * 可以声明一个属性的同时定义自己的getter和setter。

    * 可以声明具有相同名字的属性和字段,该属性会使用该字段。

    * 如果要定义private或protected属性,必须提供声明为private或protected的getter
      和setter。

    * 如果使用显式或隐式的 this(例如 this.foo, 或者 foo)访问类的在编译时定义的属性,
      Groovy会直接访问对应字段,而不是使用getter或者setter

    * 如果使用显式或隐式的 foo 访问一个不存在的属性,Groovy会通过元类(meta class)
      访问它,这可能导致运行时错误。

*/

class Foo {
    // 只读属性
    final String name = "Roberto"

    // 只读属性,有public getter和protected setter
    String language
    protected void setLanguage(String language) { this.language = language }

    // 动态类型属性
    def lastName
}

/*
  逻辑分支和循环
*/

//Groovy支持常见的if - else语法
def x = 3

if(x==1) {
    println "One"
} else if(x==2) {
    println "Two"
} else {
    println "X greater than Two"
}

//Groovy也支持三元运算符
def y = 10
def x = (y > 1) ? "worked" : "failed"
assert x == "worked"

//for循环
//使用区间(range)遍历
def x = 0
for (i in 0 .. 30) {
    x += i
}

//遍历列表
x = 0
for( i in [5,3,2,1] ) {
    x += i
}

//遍历数组
array = (0..20).toArray()
x = 0
for (i in array) {
    x += i
}

//遍历映射
def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']
x = ""
for ( e in map ) {
    x += e.value
    x += " "
}
assert x.equals("Roberto Grails Groovy ")

/*
  运算符

  在Groovy中以下常用运算符支持重载:
  http://www.groovy-lang.org/operators.html#Operator-Overloading

  实用的groovy运算符
*/
//展开(spread)运算符:对聚合对象的所有元素施加操作
def technologies = ['Groovy','Grails','Gradle']
technologies*.toUpperCase() // 相当于 technologies.collect { it?.toUpperCase() }

//安全导航(safe navigation)运算符:用来避免NullPointerException
def user = User.get(1)
def username = user?.username


/*
  闭包
  Groovy闭包好比代码块或者方法指针,它是一段代码定义,可以以后执行。

  更多信息见:http://www.groovy-lang.org/closures.html
*/
//例子:
def clos = { println "Hello World!" }

println "Executing the Closure:"
clos()

//传参数给闭包
def sum = { a, b -> println a+b }
sum(2,4)

//闭包可以引用参数列表以外的变量
def x = 5
def multiplyBy = { num -> num * x }
println multiplyBy(10)

// 只有一个参数的闭包可以省略参数的定义
def clos = { print it }
clos( "hi" )

/*
  Groovy可以记忆闭包结果 [1][2][3]
*/
def cl = {a, b ->
    sleep(3000) // 模拟费时操作
    a + b
}

mem = cl.memoize()

def callClosure(a, b) {
    def start = System.currentTimeMillis()
    mem(a, b)
    println "Inputs(a = $a, b = $b) - took ${System.currentTimeMillis() - start} msecs."
}

callClosure(1, 2)
callClosure(1, 2)
callClosure(2, 3)
callClosure(2, 3)
callClosure(3, 4)
callClosure(3, 4)
callClosure(1, 2)
callClosure(2, 3)
callClosure(3, 4)

/*
  Expando

  Expando类是一种动态bean类,可以给它的实例添加属性和添加闭包作为方法

  http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html
*/
  def user = new Expando(name:"Roberto")
  assert 'Roberto' == user.name

  user.lastName = 'Pérez'
  assert 'Pérez' == user.lastName

  user.showInfo = { out ->
      out << "Name: $name"
      out << ", Last name: $lastName"
  }

  def sw = new StringWriter()
  println user.showInfo(sw)


/*
  元编程(MOP)
*/

//使用ExpandoMetaClass增加行为
String.metaClass.testAdd = {
    println "we added this"
}

String x = "test"
x?.testAdd()

//拦截方法调用
class Test implements GroovyInterceptable {
    def sum(Integer x, Integer y) { x + y }

    def invokeMethod(String name, args) {
        System.out.println "Invoke method $name with args: $args"
    }
}

def test = new Test()
test?.sum(2,3)
test?.multiply(2,3)

//Groovy支持propertyMissing,来处理属性解析尝试
class Foo {
   def propertyMissing(String name) { name }
}
def f = new Foo()

assertEquals "boo", f.boo

/*
  类型检查和静态编译
  Groovy天生是并将永远是一门动态语言,但也支持类型检查和静态编译

  更多: http://www.infoq.com/articles/new-groovy-20
*/
//类型检查
import groovy.transform.TypeChecked

void testMethod() {}

@TypeChecked
void test() {
    testMeethod()

    def name = "Roberto"

    println naameee

}

//另一例子
import groovy.transform.TypeChecked

@TypeChecked
Integer test() {
    Integer num = "1"

    Integer[] numbers = [1,2,3,4]

    Date date = numbers[1]

    return "Test"

}

//静态编译例子
import groovy.transform.CompileStatic

@CompileStatic
int sum(int x, int y) {
    x + y
}

assert sum(2,5) == 7
```

## 进阶资源

[Groovy文档](http://www.groovy-lang.org/documentation.html)

[Groovy web console](http://groovyconsole.appspot.com/)

加入[Groovy用户组](http://www.groovy-lang.org/usergroups.html)

## 图书

* [Groovy Goodness] (https://leanpub.com/groovy-goodness-notebook)

* [Groovy in Action] (http://manning.com/koenig2/)

* [Programming Groovy 2: Dynamic Productivity for the Java Developer] (http://shop.oreilly.com/product/9781937785307.do)

[1] http://roshandawrani.wordpress.com/2010/10/18/groovy-new-feature-closures-can-now-memorize-their-results/
[2] http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize
[3] http://mrhaki.blogspot.mx/2011/05/groovy-goodness-cache-closure-results.html