一、代码块
在代码块中用def关键字定义的变量不能在外部访问,如:
try{
def msg="Hello,world!";
}
//pringln msg;
如果运行最后一行"println msg;",则会报错。
但是,在代码块中没有用def关键字声明的变量,就可以在外部访问,如:
try{
msg="Hello,world!";
}
println msg;
已经使用def定义的变量,不能再次用def定义:
def a=10;
//def a=20;
代码块是可以嵌套的:
try{
try{
try{
println "Hello,world!";
}
}
}
二、闭包
闭包是可以引用外部上下文环境的一系列语句。可以将闭包赋予一个变量,并在稍后执行。
每个闭包都有一个返回值,默认的返回值就是该闭包中最后一行语句的结果
闭包可以访问外部的变量
def x=1;
def b={
x*2;//闭包可以访问外部的变量
}
将闭包赋予一个变量将记住该闭包创建时的上下文环境,即使运行时已经超出了原来的作用域:
def c;
try{
def m=10;
c={m};
}
println c();
在此处调用c(),即使已经超出了block的作用域,但仍能输出m的值
将一个闭包放入另一个闭包,可以创建它的两个实例:
c={e={"Hello,World";};e;}
v1=c();
v2=c();
println v1==v2//在此得出false,说明c()返回了不同的实例
可以在定义闭包时声明一些参数,之后在调用闭包时将这些参数值传入闭包:
c={n-> println "Parameter="+n;}
c(10);
可以利用参数将信息从包内导出,也就是所谓的“输出参数”
c={o,p-> o<<p};
x=[];
c(x,1);
c(x,2);
c(x,3);
println x;
在闭包中,总是可以用到一个叫做it的变量,如果没有显式的定义参数,则可以用it来引用
引用
c={"Parameter=${it}"};
println c(10);
如果没有传入任何参数,it仍然存在,但是为null
闭包的参数不能使用作用域中已存在变量的名字,除了隐式变量it:
def it=10;
c={it*it};
println c(5);//在此,隐式变量it仍然引用参数5,而非外部定义的10
参数在调用闭包时可以被命名。这些被命名的参数将被组装进一个Map,并指定给闭包的第一个参数:
def x={a,b,c->a.m+a.n+a.o-b+c;};
println x(m:10,5,n:15,6,o:20);
在调用闭包x的时候,参数m:10,n:15,o:20被组装进Map赋予形参a,5、6按顺序分别赋予形参b和c,结果是46。
我们可以在闭包内部和外部查询参数的个数:
def c={a,b,c->getMaximumNumberOfParameters();}
println c(1,2,3);
println c.getMaximumNumberOfParameters();
调用闭包的时候,可以对最后的一个或几个参数应用默认值:
def c={a,b=2,c=3->a+b+c;};
println c(1);
结果输出6
一个闭包可以在最后一个参数前添加Object[]前缀来创建可变长度的参数:
def c={a,Object[] b->a+b[0]+b[1];}
println c(1,2,3);
我们可以使用一个list参数调用闭包。如果闭包没有定义一个list类型的参数,则此参数将作为分解的参数传入闭包:
def c={a,b,c->a+b+c};
println c([1,2,3]);
闭包可以通过将第一个或前几个参数固化为常量,使用curry方法进行拷贝:
def c={a,b,c->a+b+c};
def d=c.curry(1);//拷贝闭包c,并将第一个参数a固化为常量1
println d(2,3);//调用闭包d,只需要给出剩余的参数。实际使用的参数仍然是1,2,3
在闭包中,可以结合使用curry和不定长度参数:
def c={a,Object[] b->b.each({m->a=a+m;});a;};
def d=c.curry(1);
def e=d.curry(2,3);//实际参数为1,[2,3]
def f=e.curry(4);//实际参数为1,[2,3,4]
println f(5);//实际参数为1,[2,3,4,5]
闭包可以递归调用
三、函数
首先,必须使用def关键字定义函数,函数也不能嵌套使用;
其次,函数不能访问在外部通过def定义的变量:
def c=10;
def f(){
println c;//编译通过
}
//f();//运行时报错
还可以使用特殊的语法标记&将函数赋予新的命名:
def f(){
println "Hello,world!";
}
def s=this.&f;
s();
函数可以后参数,包括输入参数和输出参数;
如果两个函数的拥有不同个数的未指定类型的参数,则可以使用相同的名称
def f(a){
println a*a;
}
def f(a,b){
println a*b;
}
f(10);
f(5,10)
函数可以有返回值:
1.如果有显示地使用return关键字,则返回return指定的返回值,其后面的语句不再执行;
2.如果没有显式地使用return关键字,则返回函数最后一行语句的运行结果;
3.如果使用void关键字代替def关键字定义函数,则函数的返回值将为null。
如果一个函数与一个闭包拥有相同的名称和参数,则调用的时候将执行函数,而不是闭包:
def f(a){
return a*10;
}
def f={a->a*20};
println f(5);//输出50而不是100
函数可以接受闭包作为参数:
def f(a,Closure c){
c(a);
}
f(10){println "Parameter a = "+it;}
与闭包相同,函数可以为参数指定默认值:
def f(a,b=10){
return a+b;
}
println f(5);//输出15
函数也会将命名的参数包装进一个Map,并赋予第一个参数:
def f(a,b){
return b+a.x+a.y;
}
println f(x:2,1,y:3);//输出6
函数与闭包的相同之处还有,函数同样支持不定长度的参数、分解list作为参数,以及递归调用。
分享到:
相关推荐
学习Groovy必备文档,包括一些经验整理等,比较详细的由繁到简讲述了Groovy的知识点。
这个项目是:属于入门级别的案例,通过该案例可以很快掌握groovy相关的知识点
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
java班级管理源码 CIYOU 思源教育 该项目是基于翻转课堂实现的小学网络教育平台。 国内已经有很多尝试使用翻转课堂模式的教学网络平台,但是现在大多数的网络...相反会继续后面的教学任务,但是知识点与知识点之间是有
2.1 groovy和java的异同 2.1.1 相同点 2.1.2 不同点 2.2 基础知识 2.1.1 类声明 . 2.2.2 语言级断言(assertion) 2.2.3 groovy字符串 2.2.4 闭包(closures) 2.2.5 列表...
Grails 是一个注重成效的开源 Web...要理解这些内容,你得需要点面向对象编程和 MVC Web 应用开发的基础知识。虽然阅读 并不要求熟悉 Java,但如果熟悉的话,你肯定能从中受益。 你还会看到这些例子大量用到了 Groovy。
理解代码分离的关注点 网址结构 要求 吉特 Java 1.8 Grails 4.0.0 让项目运行起来,可以从grails网站获取帮助 IntelliJ 社区版(可选,但推荐) 任务概述 我们需要一个新页面,其中包含一个供用户输入 github 帐户...
Java基础学习 基础 进阶 ...使用了Gradle作为构建工具,将知识点分成了多个子项目,然后将所有的依赖项放在了dependency.gradle中其他的子项目引用定义的依赖,实现了依赖的统一管理 同类仓库 baeldung
1个目标文件,JNDI的使用例子,有源代码,可以下载参考,JNDI的使用,初始化Context,它是连接JNDI树的起始点,查找你要的对象,打印找到的对象,关闭Context…… ftp文件传输 2个目标文件,FTP的目标是:(1)提高...
EJB中JNDI的使用源码例子 1个目标文件,JNDI的使用例子,有源代码,可以下载参考,JNDI的使用,初始化Context,它是连接JNDI树的起始点,查找你要的对象,打印找到的对象,关闭Context…… ftp文件传输 2个目标文件...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...