在用Java编程时,大部分可执行的代码要么被封装在静态类方法(static class methods)中,要么被封装在实例方法(nstance methods)中(代码
也可以被封装在构造函数,初始化函数或初始化表达式中,但这些在这儿不重要).方法把代码封装在一对花括号里并给代码段分配一个方法名.所有
这些方法必须定义在某种类型的类里面.例如,假设你要写一个返回任意整数平方的方法,这个方法可以这样写:
package
example.math;
public
class
MyMath
{
public
static
long
square(
int
numberToSquare)
{
return
numberToSquare
*
numberToSquare;
}
}
要使用square()方法,你需要像下面一样引用类和方法
import example.math.MyMath;
int x, y;
x = 2;
y = example.math.MyMath.square(x);
// y = 4.
使用Groovy你也能完成上面的工作,不过在Groovy里面你不需要声明任何类和方法.这一切由闭包来完成.闭包是封装在花括号中的一条或几条程
序语句.闭包和方法的最大区别在于闭包不需要类和方法名.下面的代码将square()方法重写为一个闭包.
{numberToSquare ->
numberToSquare * numberToSquare
};
正如你所看到的,除了不需要声明类和分配给代码方法名.然而要说明的是,上面的例子还不能用因为没有使用闭包的方法.没有标识(方法名)我
们怎么调用这个闭包呢?方法是:把创建的闭包赋给一个变量,那么你就可以使用这个变量作为闭包的标识来调用这个闭包.
// 初始化变量
int x, y;
x = 2;
// 创佳闭包并把它赋给变量C
def c = {numberToSquare -> numberToSquare * numberToSquare }
// 使用变量C作为闭包的标识, 调用闭包
y = c.call(x);
// y = 4
闭包真正优越的地方是你可以创建闭包并把它赋给一个变量,并且可以像其他变量一样在整个程序中传递.刚开始,你可能觉得这没什么,几乎毫
无用处,但是随着你学习的深入,你会发现在Groovy里闭包无处不在.
举个例子,我们用Groovy来扩展java.util.Vector类.我们添加一个方法到Vector类里,这个方法允许你应用闭包操作向量中的所有成员.我们新建
一个类GVector如下,
package
example;
public
class
GVector
extends
java.util.Vector
{
public
GVector()
{
super
();
}
public
void
apply( c )
{
for
(i in
0
..
<
size())
{
this
[i]
=
c(
this
[i]);
}
}
}
apply()方法获得一个闭包作为输入参数,对于GVector中的每一个元素,闭包被调用传递这个元素,返回的结果值用来替换这个元素.这个思想就
是你可以使用闭包来修改GVector中的内容,这个闭包必须能够获取元素并把它转换成别的什么.
现在我们就可以调用apply()方法了.你可以传递任意你需要的闭包给apply().例如我们新建一个GVector,设置几个元素,然后将这些元素传递给
我们上面创建的那个能计算整数平方的闭包.
example.GVector gVect
=
new
example.GVector();
gVect.add(
2
);
gVect.add(
3
);
gVect.add(
4
);
c
=
{numberToSquare
->
numberToSquare
*
numberToSquare;}
gVect.apply(c);
//
GVector中的所有元素全部被平方了.
由于apply()中的闭包可以是任意的,因此你可以把任何闭包传递给apply().例如使用下面的这个闭包简单地把传递给它的元素打印出来.
example.GVector gVect = new example.GVector();
gVect.add(2);
gVect.add(3);
gVect.add(4);
c2 = {value -> println(value);}
gVect.apply(c2);
// GVector中的元素全部被打印出来.
假设你已经定义并编译了GVector这个类,那么当你运行上面的脚本时,将得到下面的结果:
C:/> groovy myscript.groovy
4
9
16
C:/>
除了把闭包赋值给变量,你也可以直接把它声明为方法的参数.例如,上面的代码可以重写为如下形式:
example.GVector gVect = new example.GVector();
gVect.add(2);
gVect.add(3);
gVect.add(4);
gVect.apply {value -> println(value);}
// GVector中的元素全部被打印出来.
这段代码的功能和前面的功能一样,只不过闭包被直接定义为apply()方法的参数.
闭包VS代码段
闭包看上去就像正规的Java或Groovy代码段,但是实际上他们并不相同.正规代码段里的代码一旦遇到就由虚拟机来执行,闭包中花括号里的代
码直到call()被调用时才被执行.上面的例子中,闭包在程序行中定义,但是当时并不执行.只有闭包明确的调用call()时才会被执行.这是闭包和
代码段的重要区别.也许他们看上去很像,但事实上两者不同.正规的Java或Groovy代码当遇到时就执行,;而闭包当且仅当call()被调用时才被
执行. to be continue...
posted on 2006-04-26 17:05
学二的猫 阅读(2499)
评论(4) 编辑 收藏 所属分类:
Groovy