这里整理了Groovy的主干知识点,适合已熟悉JAVA前提下的快速入门,这里讲述都是其核心概念,无法绕过的内容,而对于那些语法糖,花哨功能,跟java的语法差异等等,这里就不多描述了,毕竟原理都相同语法不一样而已,需要的时候看下doc套用就可以了。
1、类名和文件名可以不同,后缀为groovy
2、定义变量,基本数据类型和java一样,可以不写;号,访问权限默认public,如果类型确定则注明类型即可,类型不确定则用def name即可,方法返回类型同理:
3、定义方法,访问权限默认public,返回值类型默认是Object泛型,但是不必写return,返回类型会自动转换,例如返回‘OK’,则直接写即可
4、定义主方法,实例化对象并调用方法,println相当于System.out.println(),这是一个dsl语句,实质上就是函数领域化,System的一些方法在groovy里面是默认领域化的。
又如:
5、一个领域化的例子,导入某个类的静态方法,然后直接通过方法名调用之,注意import的方法没有()号,因为()被作用为调用方法。使用范围优先级类似于servlet中的page-request-session-context,本类的成员静态方法是不用导入的,方法领域化是将方法作为属性对待,即attribute,借助范围来解决命名冲突的:
--------------------------------------------------------------------------------
6、另外,方法领域化可以为方法起一个别名,进一步解决导入的命名冲突,如:
7、上面的写法大都是静态写法,我们来点动态的操作,如动态方法调用,这里有两个sayhello重载的方法,而我们不必知道这两个方法就可以直接call sayhello方法,如果找不到该方法会抛出异常,否则会调用该方法,如果方法存在重载,则根据入参自动调用对应的方法,如果重载中有一个是无参的方法,优先是调用有参的方法,不管是否提供参数:
这些方法都是隐式调用的,如果还需要调用sayhell()这么一个无参的方法,则需要如java的写法hello.sayhello()调用,或者say.call()显示调用,方法指针操作符(&)调用用于将一个方法的引用存储在变量中,以便以后调用它;
我们将方法打印一下,可以看出调用的是同一个对象,其实这个对象就是一个闭包对象Closure,在这个闭包中调用对应的其他方法。在java中只能实现类级及以上的闭包,不能做方法闭包,Groovy也不能在方法中定义方法,其方法闭包是通过闭包对象实现的,
8、具体的闭包实现:
闭包的定义语法{ [args] -> statement },有参数和执行内容组成,两者由->隔开,多个参数用,号隔开:
可以看到闭包是一个类型,即groovy.java.Closure闭包类,直接通过闭包名隐式调用或加上call显式调用,另外,还可以使用隐式参数:
可以看到,it是隐式参数的关键字,这样就不必声明参数,其实相当于下面的写法:
又如,使用内插字符串:
9、闭包的owner,delegate,this,来看代码就明白了,所谓调用者感知:
/**
* @author yl
*
*
*/
class Hello {
class InnerClass{
String name = 'Tom';
//该闭包所属的对象
def whoIsOwner = {at ->owner}
def whoIsOwner2 = {getOwner()}
//当前正在调用该闭包的对象
def whoIsThis = {this}
def whoIsThis2 = {getThisObject()}
//委托该闭包的对象
//显式的委托
def whoIsDelegate = {delegate.name}
def whoIsDelegate2 = {getDelegate().name}
//隐式的委托
def say = {println "my name is ${name}"}
}
class NestedClass{
String name = 'Mary'
}
def output() {
def inner = new InnerClass()
assert inner.whoIsOwner()== inner //true
assert inner.whoIsOwner2() == inner //true
assert inner.whoIsThis() == inner //true
assert inner.whoIsThis2() == inner //true
assert inner.whoIsThis2() == this //false the 'this' is the current Object that who Calling output method
assert inner.whoIsDelegate() == 'Tom' //true
assert inner.whoIsDelegate2() == 'Tom' //true
//将闭包whoIsDelegate的委托修改为nested
def nested = new NestedClass()
inner.whoIsDelegate.delegate = nested
assert inner.whoIsDelegate() == 'Mary' //true
//将闭包say的委托修改为nested
inner.say()
inner.say.delegate = nested
inner.say()
//设置闭包say的委托策略为委托者优先
inner.say.resolveStrategy = Closure.DELEGATE_FIRST
inner.say()
println inner.whoIsOwner
println inner.whoIsOwner()
}
static void main(def args) {
Hello hello = new Hello()
hello.output()
}
}
层次结构如下:
this:其中的this跟java的意义相同,表示正在调用你的当前对象,官方文档描述似乎有问题:this
corresponds to the enclosing class where the closure is defined。其实因为闭包对象参数不能使用this,所以内部一般不可能直接访问到owner以外的调用者,因此下此定义。
owner:这个也和java的意义相同,只不过在java中没有一个特性描述这一点,owner表示拥有你的对象,但这个对象不一定是正在调用你的对象
delegate:关键的一点就是delegate(委托)对象,表示借用该闭包的的对象,可以理解为换了汤不但换药,汤就是委托对象的部分,药就是该闭包的部分。但是不能理解为this,这跟谁喝汤与汤药搭配的两码事。
Groovy中的Closure类提供了上面这三个默认属性,并且提供了方法来获取他们:getThisObject(),getOwner(),getDelegate()跟三者对应。
闭包对象的委托策略决定了执行委托者和owner的请求优先级,对隐式的委托起作用:
-
Closure.OWNER_FIRST
is thedefault strategy. If a property/method exists on theowner, then it will be called onthe owner. If not, then thedelegate is used. -
Closure.DELEGATE_FIRST
reverses the logic: thedelegate is used first, then the owner -
Closure.OWNER_ONLY
will only resolve the property/method lookup on the owner: the delegate will be ignored. -
Closure.DELEGATE_ONLY
will only resolve the property/method lookup on the delegate: the owner will be ignored.
先整理到此,后续更新。。。