注釋(Comments)
和Java一樣,支持單行(使用//
)、多行(/* */
)和文檔注釋(使用/** */
)。
Shebang line
UNIX系統(tǒng)支持一種特殊的單行注釋叫作Shebang line
,用于指明腳本的運行環(huán)境,這樣就可以直接在終端中使用./xxx.groovy
運行(當然,前提是文件得有可運行的權限),而不用像groovy xxx.groovy
這樣運行:
#!/usr/bin/env groovy
println "Hello from the shebang line"
#
號必須是文件的第一個字符。
標識符(Identifiers)
普通標識符
以字母、美元符號$
或下劃線_
開始,不能以數(shù)字開始。以下是可用的標識符:
def name
def item3
def with_underscore
def $dollarStart
以下是不可用的標識符:
def 3tier // 不能以數(shù)字開始
def a+b // "+"號是非法字符
def a#b // #號也不是可用的字符
注意:在點號后,是可以使用關鍵字作為標識符的:
foo.as
foo.assert
foo.break
foo.case
foo.catch
引號標識符(Quoted identifiers)
Groovy在點表達式(dotted expression)后面可以使用引號標識符,比如persion.name
可以表示為persion.'name'
或persion."name"
。而引號中可以包含普通標識符中不支持的字符,比如空格、中檔線-
這些:
def map = [:]
map."an identifier with a space and double quotes" = "ALLOWED"
map.'with-dash-signs-and-single-quotes' = "ALLOWED"
assert map."an identifier with a space and double quotes" == "ALLOWED"
assert map.'with-dash-signs-and-single-quotes' == "ALLOWED"
其實,Groovy支持多種字符串的字面量表達形式,這些都是可以出現(xiàn)在點號后面的:
map.'single quote'
map."double quote"
map.'''triple single quote'''
map."""triple double quote"""
map./slashy string/
map.$/dollar slashy string/$
更方便的是,Groovy中的GString
支持插值,也可以用在點號后面的:
def firstname = "Homer"
map."Simson-${firstname}" = "Homer Simson" // 會被插值成map."Simson-Homer"
assert map.'Simson-Homer' == "Homer Simson"
字符串
在Groovy中字符串有兩種類型,一種是Java原生的java.lang.String
;另一種是groovy.lang.GString
,又叫插值字符串(interpolated strings)。
單引號字符串(Single quoted string)
在Groovy中,使用單引號括住的字符串就是java.lang.String
,不支持插值:
def name = 'yjiyjgie'
println name.class // class java.lang.String
三單引號字符串(Triple single quoted string)
使用三單引號括住字符串支持多行,也是java.lang.String
實例,在第一個’‘’
起始處加一個反斜杠\
可以在新一行開始文本:
def strippedFirstNewline = '''line one
line two
line three
'''
// 可以寫成下面這種形式,可讀性更好
def strippedFirstNewline = '''\
line one
line two
line three
'''
雙引號字符串(Double quoted string)
如果雙引號括住的字符串中沒有插值表達式(interpolated expression),那它就是java.lang.String
;如是有插值表達式,那它就是groovy.lang.GString
:
def normalStr = "yjiyjige" // 這是一個java.lang.String
def interpolatedStr = "my name is ${normalStr}" // 這是一個groovy.lang.GString
字符串插值(String interpolation)
在Groovy所有的字符串字面量表示中,除了單引號字符串和三單引號字符串,其他形式都支持字符串插值。字符串插值,也即將占位表達式中的結果最終替換到字符串相應的位置中:
def name = 'Guillaume' // a plain string
def greeting = "Hello ${name}" // name變量的值會被替換進去
assert greeting.toString() == 'Hello Guillaume'
當使用點號表達式時,可以只用$
代替${}
:
def person = [name: 'Guillaume', age: 36]
println "$person.name is $person.age years old"
// 注意
def number = 3.14
println "$number.toString()" // 這里會報異常,因為相當于"${number.toString}()"
println "${number.toString()}" // 這樣就正常了
插值占位符中還支持閉包,而閉包的一個好處是惰性求值(lazy evaluation):
def number = 1
def eagerGString = "value == ${number}" // 普通形式
def lazyGString = "value == ${-> number}" // 這是一個閉包
println eagerGString == "value == 1"
println lazyGString == "value == 1"
number = 2
println eagerGString == "value == 1" // eagerGString已經(jīng)被固定下來了
println lazyGString == "value == 2" // lazyGString的值會被重新計算
當一個方法的需要一個java.lang.String
變量,而我們傳遞的是一個groovy.lang.GString
實例時,GString
的toString
方法會被自動調(diào)用,看起來像我們可以直接將一個GString
賦值給一個String
變量一樣。
注意:GString
與String
的hashCode是不一樣的,即使他們最終結果一樣。所以,在Map中,不應該用GString
去做元素的Key,而又使用普通的String
去取值:
def key = "a"
def m = ["${key}": "letter ${key}"] // key類型是一個GString
assert m["a"] == null // 用一個普通String類型的key去取值
三雙引號字符串(Triple double quoted string)
類似于三單引號字符串,但支持字符串插值。
斜線字符串(Slashy string)
除了使用引號來括住字符串,還可以使用/
。它一般用來定義正則表達式:
def fooPattern = /.*foo.*/
assert fooPattern == '.*foo.*'
def foo = /"yjiyjige"/ // 可以在斜線表達式中,直接使用引號
println foo // 結果是“yjiyjige”
美元斜線字符串(Dollar slashy string)
這種字符串使用$/
開始,使用/$
結束,其中的轉(zhuǎn)義字符為$
:
def name = "Guillaume"
def date = "April, 1st"
def dollarSlashy = $/
Hello $name,
today we're ${date}.
$ dollar sign
$$ escaped dollar sign
\ backslash
/ forward slash
$/ escaped forward slash
$/$ escaped dollar slashy string delimiter
/$
assert [
'Guillaume',
'April, 1st',
'$ dollar sign',
'$ escaped dollar sign',
'\\ backslash',
'/ forward slash',
'$/ escaped forward slash',
'/$ escaped dollar slashy string delimiter'
].each { dollarSlashy.contains(it) }
字符串小結
字符(Characters)
在Groovy中并沒有明確的字符字面量表示形式,我們必須明確指明:
char c1 = 'A' // 明確指定給一個字符變量
assert c1 instanceof Character
def c2 = 'B' as char // 用as關鍵字
assert c2 instanceof Character
def c3 = (char) 'C' // 強制類型轉(zhuǎn)換
assert c3 instanceof Character
數(shù)字(Numbers)
當使用def
指明整數(shù)字面量時,變量的類型會根據(jù)數(shù)字的大小自動調(diào)整:
def a = 1
assert a instanceof Integer
// Integer.MAX_VALUE
def b = 2147483647
assert b instanceof Integer
// Integer.MAX_VALUE + 1
def c = 2147483648
assert c instanceof Long
// Long.MAX_VALUE
def d = 9223372036854775807
assert d instanceof Long
// Long.MAX_VALUE + 1
def e = 9223372036854775808
assert e instanceof BigInteger
為了精確地計算小數(shù),在Groovy中使用def
聲明的小數(shù)是BigDecimal
類型的:
def decimal = 123.456
println decimal.getClass() // class java.math.BigDecimal
如果要強制指明一個數(shù)字的字面量類型,可以給字面量加上類型后綴:
-
BigInteger
使用G
或g
-
Long
使用L
或l
-
Integer
使用I
或i
-
BigDecimal
使用G
或g
-
Double
使用D
或d
-
Float
使用F
或f
列表(List)
默認情況下Groovy的列表使用的是java.util.ArrayList
,用中括號[]
括住,使用逗號分隔:
def numbers = [1, 2, 3]
println numbers.getClass() // class java.util.ArrayList
如果要使用其它類型的列表(如:LinkedList
)可以使用as
操作符或顯式分配給一個指定類型的變量:
def arrayList = [1, 2, 3] // 默認類型
assert arrayList instanceof java.util.ArrayList
def linkedList = [2, 3, 4] as LinkedList // 使用as操作符
assert linkedList instanceof java.util.LinkedList
LinkedList otherLinked = [3, 4, 5] // 顯式指明類型
assert otherLinked instanceof java.util.LinkedList
Groovy重載了列表的[]
和<<
操作符,可以通過List[index]
訪問指定位置元素,也可以通過List << element
往列表末尾添加元素:
def letters = ['a', 'b', 'c', 'd']
assert letters[0] == 'a'
assert letters[1] == 'b'
assert letters[-1] == 'd' // 從后面訪問
assert letters[-2] == 'c'
letters[2] = 'C' // 直接修改
assert letters[2] == 'C'
letters << 'e' // 往最后面添加元素
assert letters[4] == 'e'
assert letters[-1] == 'e'
assert letters[1, 3] == ['b', 'd'] // 提取指定元素
assert letters[2..4] == ['C', 'd', 'e'] // 支持范圍(ranges)操作
// 二維列表
def multi = [[0, 1], [2, 3]]
assert multi[1][0] == 2
數(shù)組(Arrays)
在Groovy中,沒有數(shù)組的字面量定義方式。和特定類型列表的定義方式一樣,我們需要使用as
操作符或顯式地分配給一個數(shù)組類型的變量:
String[] arrStr = ['Ananas', 'Banana', 'Kiwi'] // 顯式指明類型
assert arrStr instanceof String[]
assert !(arrStr instanceof List)
def numArr = [1, 2, 3] as int[] // 使用as操作符
assert numArr instanceof int[]
assert numArr.size() == 3
映射(Maps)
Groovy使用中括號[]
來定義映射,元素需要包含key和value使用冒號分隔,元素與元素之間用逗號分隔:
// key部分其實是字符串
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
assert colors['red'] == '#FF0000' // 使用中括號訪問
assert colors.green == '#00FF00' // 使用點表達式訪問
colors['pink'] = '#FF00FF'
colors.yellow = '#FFFF00'
assert colors.pink == '#FF00FF'
assert colors['yellow'] == '#FFFF00'
assert colors instanceof java.util.LinkedHashMap // 默認使用LinkedHashMap類型
在上邊的例子中,雖然沒有明確的使用字符串’red‘
、’green‘
,但Groovy會自動把那些key轉(zhuǎn)化為字符串。并且,在默認情況下,初始化映射時,key也不會去使用已經(jīng)存在的變量:
def keyVal = 'name'
def persons = [keyVal: 'Guillaume'] // 此處的key是字符串keyVal而不是name
assert !persons.containsKey('name')
assert persons.containsKey('keyVal')
如果要使用一個變量作為key,需要用括號括住:
def keyVal = 'name'
def persons = [(keyVal): 'Guillaume'] // 相當于[ 'name' : 'Guillaume' ]
assert persons.containsKey('name')
assert !persons.containsKey('keyVal')