字符串

Groovy 中既可以使用”也可以使用'来标识字符串。你可以方便的使用其中的任何一种引用方式来标识字符串。例如:

println "he said 'cheese' once"
println 'he said "cheese!" again'

Groovy解析器可以支持\uab12(也就使在\u后跟随一个精确的16进制数字)这样的表示方法,这种表示方法可以用在字符串内部或者其他任何地方,就如同java的解析器一样。

连结

字符串之间可以使用”+“进行连接。例如:

#!/usr/bin/env groovy
 
a = "world"
print "hello " + a + "\n"

多行字符串

Groovey字符串规则中,不支持字符串跨越多行。

但是有一个例外,你可以在字符串行尾使用反斜线来连接下面的行的内容。

// 这里会在编译的时候报错
def foo = "hello
//这样可以通过
def foo = "hello\
world."

(译者注:使用反斜线连接两行的内容,实际上字符串表示的是一行的内容,上例总如果打印foo,会发现打印的是一行hello world。)

如果你有一段的文本,你并不希望编译器把它当做代码进行编译(例如:一段HTML代码),此时你可以使用””“语法。

def name = "James"
def text = """\
hello there ${name}
how are you today?
"""
 
assert text != null
println(text)

由于前面加了反斜线,所以字符串文本实际上包含两行。而且不管操作系统中的行结束符号是什么,这里都用'\n'来表示。

反斜杠(Slashy)字符串语法

使用另外一种表示方法来补充字符串语法,使之无需额外的反斜杠来标识转义特殊字符是可能的。这与正则表达式或者Windows目录路径名尤其相似。

def s = /.*foo.*/
def dirname  = /^.*\//
def basename = /[^\/]+$/

斜杠字符串唯一支持的转义字符是用\/来向字符串中插入一个斜杠。这样做的后果是在斜杠字符串中你不能用一个反斜杠来作为一个字符串的最后一个字节(否则 Groovy会认为你正试图转义字符串的终结符——因此也不会知道你其实已经终结了字符串):替代用法:def bs ='\\\\', def winpath = /C:\windows\system32$bs/ 或者 def winpath =/C:\windows\system32\${}/.

另外一个提示:不要尝试使用空斜杠字符串: def x = //, 斜杠会被看作注释行的定界符, 但是def z = /${}/可行。

最后的提示:当你消去一个断言语句中的括号的时候,目前不允许斜杠字符串出现在断言表达式的左手边,例如:

assert 'ab' == 'a' + 'b'    // OK, 没有斜杠字符串
assert 'a' + 'b' == /ab/    // OK, 斜杠字符串在右手边
assert (/ab/ == 'a' + 'b')  // 斜杠字符串在左手边时括号不能消去

当前的这个语法特点不是一个理想的语法,有一天该不正常现象可能会被消除——这是语法中一个棘手的案例。

更多的例子,请参考正则表达式.

String是不可变的

下面两个代码段可以得出这一结论,你可以把代码复制粘贴到groovy控制台:

st = ["status":"test"]
sn = st
println sn
st.status = "tset"
println sn

以上两个变量都是对map的引用。

如果你对字符串做同样的动作,结果就不同:

st = "test"
sn = st
println sn
st = "tset"
println sn

这是Guillaume Laforge的解释:

第一个例子中sn和st指向内存中同一个map对象,而在第二个代码段的尾部,st则指向内存中代表一个新的不可改变字符串的另一位置。

GString

在双引号(也就是,单个双引号或者多行字符串使用的三个双引号)中声明的字符串可以包含任意表达式,就如同上面所示的使用类似于JSP EL、Velocity和Jexl的${expression}的语法。任何合法的Groovy表达式,包括方法调用等等,都可以包围在${…}中。定义GString的方法与在Java中创建普通的字符串一样。这里是包含了一个简单的变量和一个表达式的一个简单例子:

foxtype = 'quick'
foxcolor = ['b', 'r', 'o', 'w', 'n']
println "The $foxtype ${foxcolor.join()} fox"
// => The quick brown fox

真正发生的事情是,当一个字符串表达式包含了一个${…}表达式时,一个GString对象会被创建,而不是一个普通的java.lang.String实例,而该GString对象包含了文本和该字符串所用到的值。

GString可以涉及惰性求值(lazy evaluation),所以直到toString()方法被调用,GString才会被求值。这种惰性求值对于某些情况(如写日志)非常有用,譬如它允许字符串的计算、对值的toString()的调用,和不同字符串的连接可以惰性的完成(如果可能的话)。这里是一个说明了惰性求值的例子:

println new Date()
x = "It is currently ${ new Date() }"
y = "It is currently ${ writer -> writer << new Date() }"
sleep 5000
println x
println y

输出如下:

Thu Apr 17 23:18:17 EST 2008
It is currently Thu Apr 17 23:18:17 EST 2008
It is currently Thu Apr 17 23:18:22 EST 2008

为了解释这个输出,我们需要知道一个我们还没提到过的关于GString的附加规则。它包括了根据闭包的参数个数对一个GString中的闭包表达式进行求值的不同规则。规则如下:

  • 如果闭包有0个参数,那么调用该闭包,并以其返回值作为GString中该处的值
  • 如果闭包有1个参数,则以一个Writer作为参数调用该闭包,并以写到该Writer的字符作为GString中该处的值
  • 如果闭包有多于1个参数,则抛出GroovyRuntimeException。

所以,在上面的例子中,x包含一个含0个参数的闭包,这意味着new Date()会被调用,并且该值会被作为一个GString的值存储起来。当我们后来尝试输出x时,已计算的值被放到GString中的适当位置,而输出的是GString被定义的时间。但是,y包含一个含1个参数参数的闭包,这意味着该闭包表达式会被储存在GString中。但我们输出y时,该闭包会被调用,而输出的是输出时的时间。

另外一个GString的用例是GSQL,它的参数可以使用相同的机制传给SQL语句,这为整合Groovy和其他语言(如SQL)提供了一个简洁的方法。然后GroovySql把表达式转换为?,并使用一个JDBC PreparedStatement,最后把值传进去,并保留它们的类型。

如果你想明确的把GString强制转换为一个String,你可以使用toString()方法。Groovy也可以为你自动的把GString强制转换为String。

String和StringBuffer方法

请查看:JN1525-字符串

更多示例

下面的例子都通过测试:

aaa = '"bread","apple","egg"'
items = aaa.split(',')
assert items[1] == '"apple"'
items.each{ println "item: $it" }

输出结果

item: "bread"
item: "apple"
item: "egg"
 
 
wiki/user_guide/strings.txt · 最后更改: 2008-07-22 23:29 由 johnny
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki