Groovy基础语法
动态类型
Groovy定义变量时:可以用Groovy风格的def声明,不指定类型;也可以兼容Java风格,指定变量类型;甚至还可以省略def或类型
def t1 = 't1' String t2 = 't2' t3 = 't3'
Groovy风格定义的变量类型是动态的,编译成class时会自动转换成正确的Java类型
def var = 'text' println var var = 5 println var + 1
可用Java实现类似效果如下
Object o = "text"; System.out.println(String.valueOf(o)); o = 5; System.out.println(String.valueOf(Integer.valueOf(o) + 1));
字符串
Groovy支持灵活的字符串语法,例如:
// 单引号字符串 def a = 'hello "world"' // 双引号字符串 def b = "What's the weather like?" // 用加号连接字符串,用等号对比字符串 assert 'ab' == 'a' + 'b' // 三个单引号字符串,支持直接换行 def aMultilineString = '''line one line two line three''' // 斜线字符串中,反斜线不需要转义,常用于正则表达式 def fooPattern = /.*foo.*/ // 双引号字符串支持用$嵌入变量 def name = 'Tom' def greeting = "Hello ${name}" // 如需函数调用,则$后表达式要加大括号 def pi = 3.14 def piString = "Pi = ${pi.toString()}"
闭包 (Closure)
- 闭包是一个变量,又是一个函数,类似C语言中的函数指针,或者Java中只有一个方法的接口(Runnable等)
- 反编译class文件可以看出,Groovy闭包都会转化为继承groovy.lang.Closure的类
- 闭包方法的参数用箭头定义,如果不特殊指定,则默认有一个it参数
- 闭包方法的返回值可以用return显示指定,如果不指定则使用最后一条语句的值
def c1 = { println 'hello' } def c2 = { a, b -> println a println b } def c3 = { int a, String b -> println a println b } def c4 = { -> println 'hello' } def c5 = { println it } def c6 = { return it + 1 } def c7 = { it + 1 }
闭包调用可以用call,也可以直接像Java方法一样加括号调用。
def c = { println it } c.call('text1') c('text2')
Java实现闭包效果:
abstract class MyClosure { abstract void call(Object o); } MyClosure c = new MyClosure() { @Override void call(Object o) { System.out.println(String.valueOf(o)); } }; c.call("text");
方法/闭包的定义与调用
Groovy中定义方法既可以用Groovy闭包风格,也可以用Java风格,参数/返回值类型也是可选的
def f1 = { text -> println text } def f2(text) { println text } void f3(String text) { println text }
注意函数定义不能这么写,会被视为函数调用
f4(text) { println text }
调用带参数的闭包/函数,通常可以省略括号,如果最后一个参数是闭包,还可以单独写在括号后面,如下:
println('hello') println 'hello' def func = { text, Closure closure -> println text closure.call() } func('1', { println '2' }) func '3', { println '4' } func('5') { println '6' }
delegate,owner,this
查看Closure类的源码,可以发现闭包中有delegate、owner、this三个成员变量,调用闭包没有的属性/方法时,会尝试在这三个变量上调用。一般情况下:
this
指向闭包外部的Object,指定义闭包的类。owner
指向闭包外部的Object/Closure,指直接包含闭包的类或闭包。delegate
默认和owner一致,指用于处理闭包属性/方法调用的第三方对象,可以修改。
在闭包构造时this和owner就已经确定并传入,是只读的。如果需要修改,可以用Closure.rehydrate()方法克隆新的闭包,同时设置其this和owner。
Closure还有一个resolveStrategy属性,有多种值(OWNER_FIRST、DELEGATE_FIRST、OWNER_ONLY、DELEGATE_ONLY、TO_SELF),默认为OWNER_FIRST,表示调用闭包没有定义的属性/方法时,先尝试从owner取,再尝试从delegate取。
Groovy代码示例:
class MyDelegate { def func = { println('hello') } } def c = { func() } c.delegate = new MyDelegate() c.call()
用Java实现类似效果如下:
static boolean callMethod(Object o, String method, Object... args) { try { Method func = o.getClass().getDeclaredMethod(method); if (func != null) { func.invoke(o, args); return true; } } catch (Exception ignored) { } return false; } class MyDelegate { void func() { System.out.println("func"); } } abstract class MyClosure { Object delegate; abstract void call(); } MyClosure c = new MyClosure() { @Override void call() { if (!callMethod(this, "func")) { callMethod(delegate, "func"); } } }; c.delegate = new MyDelegate(); c.call();
属性与Getter、Setter
Groovy中对象的属性(通常即成员变量)可以直接用名字访问,实际上会调用getter和setter// File没有absolutePath的成员变量,但有getAbsolutePath方法,可以直接当属性访问
println new File('text').absolutePath // File没有setAbsolutePath方法,这句会报ReadOnlyPropertyException new File('text').absolutePath = '1'