Groovy基础

来源:互联网 发布:免费网络加速器 编辑:程序博客网 时间:2024/05/01 05:05

这里整理了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 //trueassert inner.whoIsOwner2() == inner //trueassert inner.whoIsThis() == inner //trueassert inner.whoIsThis2() == inner //trueassert inner.whoIsThis2() == this //false the 'this' is the current Object that who Calling output method assert inner.whoIsDelegate() == 'Tom' //trueassert inner.whoIsDelegate2() == 'Tom' //true//将闭包whoIsDelegate的委托修改为nesteddef nested = new NestedClass()inner.whoIsDelegate.delegate = nestedassert inner.whoIsDelegate() == 'Mary' //true//将闭包say的委托修改为nestedinner.say()inner.say.delegate = nestedinner.say()//设置闭包say的委托策略为委托者优先inner.say.resolveStrategy = Closure.DELEGATE_FIRSTinner.say()println inner.whoIsOwnerprintln 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.

如果你使用过java的Thread.currentThread.getStackTrace()或者new Throwable().getStackTrace(),应该对调用者感知特性不陌生,在这之前还有sun.reflect.Reflection,可以实现类似上述委托策略的调用者感知操作,但是该方法被否决过很多次,原因是影响了程序的健壮性,故java一致没有将sun包的东西标准化,后续的版本也废弃了该方法,但是该方法任然是groovy的一个主力方法,所以受影响也比较大。不过我觉得只要能保证安全的情况下,使用都无妨,视场合而定。


先整理到此,后续更新。。。

原创粉丝点击