10、闭包(Closure)
闭包是用中括号括起来的代码块,可以被单独调用或运行,也可以被命名
l 闭包常用于对集合进行迭代:
map.each {key,val -> println "$key:$val"} //key和val用于接收map每个元素的键和值
map.each { println it } //关键字it代表当前迭代map元素
map.each { println it.getKey()+"->"+it.getValue() }
l 除了迭代外,闭包还可以单独使用:
def say = {word ->
println word
}
say 'hello' //调用
say.call 'hello' //调用
实际上,闭包是个对象,可以作为参数传递,也和单独调用,甚至作为方法的返回值,有点像Java中的内部类。其作用和C++中的函数指针类似
注意:凡是几乎或一系列的内容,都可以使用each进行闭包迭代,包括Map、Collection、JDBC Rowset、File的行等等
11、类
你可以用标准Java Bean的语法来定义一个Groovy类。但是,我们完全可以用Groovy的方式定义和使用类,这样可以减少一半以上JavaBean的代码:
(1)不需要public修饰符
Groovy默认的访问方式就是public
(2)不需要类型说明
Groovy不关心变量和方法参数的类型
(3)不需要getter/setter方法
Public字段不需要提供getter/setter方法,因为Groovy在字节码中生成相应的getter/setter方法
(4)不需要构造方法
因为Groovy自动提供的构造方法已经够使用了。一个是无参构造函数,另一个是只有Map类型构造参数的构造方法(可以用它来初始化任何类成员字段)
(5)不需要return
Groovy不需要方法返回值(默认返回方法最后一条语句产生的值)
(6)方法调用可以不使用圆括号
构造方法除外
12、?运算符和*.运算符
l ?运算符
rs?.next()
和下面代码等价:
if(rs != null){
rs.next();
}
l *.运算符
用于对集合类型的对象的每个元素执行相同的方法,返回值为大小和该集合元素相同的List
def col = ['123','1','12345']
println col*.size()
13、 枚举(Enum)
l 简单的例子:
enum Day{
SUNDAY, MONDAY, TUESDAY,WEDNESDAY,
THURSDAY, FRIDAY,SATURDAY
}
def today = Day.SUNDAY
switch(today){
case [Day.SATURDAY,Day.SUNDAY]:
println 'Weekends'
break
case Day.MONDAY..Day.FRIDAY:
println 'Workdays'
break
default:
println 'Not a valid Day!'
}
注意,switch和case中可以使用任何对象,case中还可以使用List和“范围”
l Groovy支持带构造器、属性和方法的enum:
enum Planet{
MERCURY(3.303e+3, 2.4397e6),
VERNUS(4.869e24, 6.0518e6),
EARTH(5.869e24, 6.37814e6),
MARS(6.421e24, 3.3972e6),
JUPITER(1.9e27, 7.1492e6),
SATURN(5.688e26, 6.0268e6),
URANUS(8.686e25, 2.5559e7),
NEPTUNE(1.024e26, 2.4746e7)
double mass
double radius
Planet(double mass, double radius){
this.mass = mass;
this.radius = radius
}
void printMe(){
println "${name()} has a mass of ${mass}"+
" and a radius of ${radius}"
}
}
Planet.EARTH.printMe()
14、Elvis操作符
Elvis是三目运算符“?:”的简称。
l 三目运算符通常以以下形式出现:
String displayName = name!=null?name:"Unknown"
l 在Groovy中,可以简化为下面写法:(因为在Groovy中,null可以转换为false)
String displayName = name?name:"Unknown"
l 基于“不重复”原则,Elvis可以再次简化为:
String displayName = name?:"Unknown"
15、动态性
Groovy所有的对象都有一个元类metaClass,可以通过对象的metaClass属性访问该元类,我们可以通过元类向对象动态添加方法,查看对象的属性和方法(反射)
l 动态添加一个方法:
def msg = "hello"
msg.metaClass.up = {msg.toUpperCase()}
l 打印所有属性和方法:
msg.metaClass.metaMethods.each { println it }
msg.metaClass.properties.each { println it }
l 查找属性和方法:
if( msg.metaClass.respondsTo (msg, "up")){
println msg.up()
}
if( msg.metaClass.hasProperty(msg,"bytes")){
println msg.bytes.encodeBase64()
}
单元测试
利用JUnit可以用两种方式对Groovy进行单元测试
被测试的Groovy类,代码如下:
class Person {
def Name
def Age
@Override
public String toString() {
"Name:${Name}, Age:${Age}"
}
}
l 方式一:使用JUnit TestCase(Java类)
实际上是对Java class(字节码)进行的测试,代码如下:
import org.junit.Test;
public class JavaTestPerson {
@Test
public void test(){
Person p = new Person();
p.setName("Name");
p.setAge(1);
System.out.println(p);
}
}
l 方式二:使用Groovy类进行测试
import org.junit.Test
class GroovyTestPerson {
@Test
public void test(){
Person p = new Person(Name:"name",Age:1)
println p
}
}
<!--EndFragment-->