Groovy Gpath
两个类之间的访问
class Address{
String prov
String city
}
class Person{
String id
String name
Address addr // 关联地址类
}
//Gpath来操作它们
def addr = new Address(prov:'Hubei',city:'Xiaogan')
def person = new Person(id:123,name:'Wallace',addr:addr)
println person.name
println person.addr.city
值得注意的是,上面的嵌套访问并不是安全的。请看下面的例子:
def person = new Person(id:123,name:'Wallace')
println person.addr.city
- 这样的访问就会报空指针的错误。为了解决这种空指针的错误,在Java语言中通常要做如下的非空判断:
if(person!=null&&person.addr!=null){
println person.addr.city
}
- groovy处理简单很多,只要用
?.
操作即可,它的结果是如果Gpath访问的对象存在,则返回结果;否则返回null
def person = new Person(id:123,name:'Wallace')
println person?.addr?.city
对xml的操作
def text = """
<persons>
<person sex='male'>
<id>1</id>
<name>Tom</name>
</person>
<person sex='female'>
<id>2</id>
<name>Alice</name>
</person>
</persons>
"""
def node = new XmlSlurper().parseText(text)
node.person.each{
println it.name
}
Gpath对XML的访问不会存在空指针的情况,而会直接返回null。请看下面的例子:
println node.p.x
访问GroovyBean
用Gpath访问GroovyBean对象的属性并不是直接访问该属性,而是通过“set”和“get”方法进行的
class Person
{
String id
String name
Address addr
def getName()
{
return 'Tom'
}
}
在上面的“Person”类中,我们自己定义了“getName”方法,让它永远返回“Tom”,下面,我们使用Gpath来测试它:
def person = new Person(id:123,name:'Wallace')
println person.name
运行结果为:
Tom
由于我们在“person”对象的定义中设置了“name”属性的值为“Wallace”,很明显,“person”对象的“name”属性值为“Wallace”,但我们使用“person.name”访问的返回值只能是“Tom”,因为方法“getName”永远返回“Tom”。
当然,我们也有办法访问属性的真实值,这就是使用.@
操作符。请看下面的例子
def person = new Person(id:123,name:'Wallace')
println person.name
println person.@name
运行结果为:
Tom
Wallace
“.@”操作xml
通过Gpath访问XML的时候,“.@”操作符也有它自己的用途。请看下面的例子:
def text = """
<persons>
<person sex='male'>
<id>1</id>
<name>Tom</name>
</person>
<person sex='female'>
<id>2</id>
<name>Alice</name>
</person>
</persons>
"""
def node = new XmlSlurper().parseText(text)
node.person.each{
println it.@sex
}
运行结果为:
male
female
可以看出,使用“.@”操作符可以访问一个节点的属性。
Groovy的展开操作符(Spread Operator)*.
和*
*.
操作符称之为:spread-dot操作,即“展开(点)”操作。比如
list*.member
list.collect{ item -> item?.member }
上面的是等效的。此处member可以是属性,也可以是get/set方法,甚至是一般的方法。如下例:
class SpreadDotDemo {
def count
}
def list = [new SpreadDotDemo(count:1),new SpreadDotDemo(count:2),new SpreadDotDemo(count:5) ]
assert 8==list*.count.sum()
assert 8==list.count.sum()//去掉*也可以的
“*.”也是安全解引用操作符(Safe Dereference Operator也称为提领运算符),用以避免NullPointerException。
def SpreadDotDemo demo
demo.count //将抛空指针异常
demo*.count //避免了null的检查,并返回null
- 跟spead doc操作符相关的事spead操作(*),它可以看作是逗号分隔的list的下标操作符的逆操作
def getList(){
return [1,2,3]
}
def sum(a,b,c){
return a + b + c
}
assert 6 == sum(*list)
def range = (1..3)
assert [0,1,2,3] == [0,*range]
相同的戏法同样可以应用在 map 上:
def map = [a:1,b:2]
assert [a:1, b:2, c:3] == [c:3, *:map]