赞
踩
Groovy单行注释以//
开头,可以出现在程序的各个位置。
- // a standalone single line comment
- println "hello" // a comment till the end of the line
多行注释以 /*
开头,以 */
结尾,可以出现在程序的任何位置。
- /* a standalone multiline comment
- spanning two lines */
- println "hello" /* a multiline comment starting
- at the end of a statement */
- println 1 /* one */ + 2 /* two */
GroovyDoc以 /**
开头,以 */
结尾,中间行一般可以选择性的以 *
开头。
GroovyDoc一般用于:
- /**
- * A Class description
- */
- class Person {
- /** the name of the person */
- String name
- /**
- * Creates a greeting method for a certain person.
- *
- * @param otherPerson the person to greet
- * @return a greeting message
- */
- String greet(String otherPerson) {
- "Hello ${otherPerson}"
- }
- }
以#
开头写在文件的第一行,告诉Unix或类Unix系统以何种解释器去运行脚本。前提是已经安装了Groovy,并且配置完PATH。
- #!/usr/bin/env groovy
- println "Hello from the shebang line"
as assert break case catch class const continue def default do else enum extends false finally for goto if implements import in instanceof interfacenew null package return super switch this throwthrows trait true try while
标识符以字母、$、_开头,不能以数字开头,但后面可以跟数字。
字母的的取值区间为:
eg:
- def name
- def item3
- def with_underscore
- def $dollarStart
引用标识符是.(dot)
后的表达式。比如说name
是person.name
的一部分,那么我们可以通过person."name"
或者person.'name'
来引用它。这点与Java不同,Java不允许这种格式的引用。eg:
- 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提供了不同种类的字符串字面量,所有String类型的字面量都允许写到.
后作为引用标识符。eg:
- map.'single quote'
- map."double quote"
- map.'''triple single quote'''
- map."""triple double quote"""
- map./slashy string/
- map.$/dollar slashy string/$
Groovy支持java.lang.String
和GString(groovy.lang.GString)
字符串类型,其中GString在一些编程语言中被称作interpolated strings。Wikipedia - String interpolation
单引号字符串被解释成java.lang.string
,不支持内插值。
'a single quoted string'
Groovy中连接字符串使用+
。
assert 'ab' == 'a' + 'b'
三单引号字符串被解释成java.lang.String
类型,不支持内插值。
三单引号支持多行,支持文本跨行,并且不需要换行符,字符串原样输出。eg:
- def aMultilineString = '''line one
- line two
- line three'''
通常,代码在格式化完毕之后,会保持缩进。对于三单引号字符串来说,会把缩进也原样输出。Groovy提供了String#stripIndent()
方法来去掉字符串前的缩进,并且提供了String#stripMargin()
方法,可以删除字符串开始位置的指定分隔符。
当我们创建如下的字符串时:
- def startingAndEndingWithANewline = '''
- line one
- line two
- line three
- '''
会发现字符串开头包含一个换行符\n
,可以通过字符串开头添加``来消除开头的换行符。
- def strippedFirstNewline = '''\
- line one
- line two
- line three
- '''
- assert !strippedFirstNewline.startsWith('\n')
"a double quoted string"
当双引号字符串中没有插值表达式时,字符串的类型为java.lang.String
,当双引号字符串中包含插值表达式时,字符串类型为groovy.lang.GString
。
除了单引号字符串和三单引号字符串以外,任何Groovy表达式可以出现在所有的字符串字面量中。插值实际上是替换字符串中的占位符。占位符表达式是被${}
围绕或以$
为前缀的点表达式(dotted expressions)
,当GString传递给一个以String类型作为参数的方法时,会调用toString
方法,将占位符替换为表达式所代表的值。eg:
- def name = 'Guillaume' // a plain string
- def greeting = "Hello ${name}"
- assert greeting.toString() == 'Hello Guillaume'
- def sum = "The sum of 2 and 3 equals ${2 + 3}"
- assert sum.toString() == 'The sum of 2 and 3 equals 5'
实际上
${}
中不仅可以使用表达式,也可以写声明语句,但是这些语句的返回值为null,例如"The sum of 1 and 2 is equal to ${def a = 1; def b = 2; a + b}"
在Groovy中是被支持的,但是一般在Groovy中不推荐这样写。更好的写法是在GString中只使用简单的占位符。
使用$
和点表达式(dotted expressions)
,eg:
- def person = [name: 'Guillaume', age: 36]
- assert "$person.name is $person.age years old" == 'Guillaume is 36 years old'
使用$
和点表达式(dotted expressions)
的时候,只允许a.b
,a.b.c
的写法,不能调用方法,否则会抛出groovy.lang.MissingPropertyException
的异常。因为Groovy在替换插值时调用的是toString
方法。
- def number = 3.14
-
- shouldFail(MissingPropertyException) {
- println "$number.toString()" // groovy.lang.MissingPropertyException
- }
将 "$number.toString()"
替换为 "${number.toString}()"
可以正常运行。
闭包表达式的格式为:${->}
,简单的理解为一个闭包前面加了一个$
符号。eg:
- def sParameterLessClosure = "1 + 2 == ${-> 3}"
- assert sParameterLessClosure == '1 + 2 == 3'
-
- def sOneParamClosure = "1 + 2 == ${ w -> w << 3}"
- assert sOneParamClosure == '1 + 2 == 3'
关于闭包表达式:
java.io.StringWriter
参数,可以通过追加内容到>>
后面的方式添加。闭包表达式只能有0个或1个参数。
闭包表达式和普通表达式唯一的不同是:lazy evaluation 。详情移步 —> Wikipedia - Lazy evaluation
- def number = 1
- def eagerGString = "value == ${number}"
- def lazyGString = "value == ${ -> number }"
-
- assert eagerGString == "value == 1"
- assert lazyGString == "value == 1"
-
- number = 2
- assert eagerGString == "value == 1" // eagerGString不会再次求值
- assert lazyGString == "value == 2" // lazyGString会再次求值
尽管GString可以代替String,但是他们还一处不同:他们的hashCodes不同。原生的Java String 是immutable(不可变的),但是GString所表示的String却是可变的,依赖于的它的插值。即使GString和Java原生String类型有相同的字面量,它们的hashCodes的值可能不同。eg:
assert "one: ${1}".hashCode() != "one: 1".hashCode()
由于GString和String的hashCodes不同,所以应该避免使用使用GString作为Map的key。eg:
- def key = "a"
- def m = ["${key}": "letter ${key}"]
- assert m["a"] == null
类似于三单引号字符串,支持跨行。也类似双引号字符,支持GString插值操作。
- def name = 'Groovy'
- def template = """
- Dear Mr ${name},
- You're the winner of the lottery!
- Yours sincerly,
- Dave
- """
-
- assert template.toString().contains('Groovy')
以/
作为界定符的字符串,叫做Slashy string。它通常被用于写正则表达式,因为不需要转译的反斜线``。
- def fooPattern = /.*foo.*/
- assert fooPattern == '.*foo.*'
如果字符串中间出现/
,这种情况下才需要转译。eg:
- def escapeSlash = /The character \/ is a forward slash/
- assert escapeSlash == 'The character / is a forward slash'
Slashy string允许跨行,eg:
- def multilineSlashy = /one
- two
- three/
-
- assert multilineSlashy.contains('\n')
Slashy string支持插值操作,类似GString。eg:
- def color = 'blue'
- def interpolatedSlashy = /a ${color} car/
-
- assert interpolatedSlashy == 'a blue car'
如果Slashy string是空字符串
//
,那么编译过程中会把//
当做注释。
Dollar slashy string相当于跨行的GString,以$/
开头,以/$
结尾。以$
作为转译字符,可以转译另一个$
或/
。
Groovy没有明确的字符类型,可以通过以下三种方式创建:
- char c1 = 'A' // 类型声明为char
- assert c1 instanceof Character
-
- def c2 = 'B' as char // 通过as将类型强制指定为char
- assert c2 instanceof Character
-
- def c3 = (char)'C' // 通过类型转换
- assert c3 instanceof Character
Groovy的整型和Java类似:
byte
char
short
int
long
java.lang.BigInteger
eg:
- // primitive types 原始类型
- byte b = 1
- char c = 2
- short s = 3
- int i = 4
- long l = 5
-
- // infinite precision 引用类型
- BigInteger bi = 6
如果使用def
声明类型,那么这个整型是可变的。它会数值的大小来匹配类型。(负数也如此)
- 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
其它进制:
0b
开头的数字0
开头的数字0x
开头的数字浮点数类型和Java类似:
float
double
java.lang.BigDecimal
浮点数类型支持指数,通过e
或E
实现。
- // primitive types
- float f = 1.234
- double d = 2.345
-
- // infinite precision
- BigDecimal bd = 3.456
-
- assert 1e3 == 1_000.0
- assert 2E4 == 20_000.0
- assert 3e+1 == 30.0
- assert 4E-2 == 0.04
- assert 5e-1 == 0.5
为了计算的准确性,Groovy使用BigDecimal作为浮点数的默认类型。除非显示的声明float
或double
,否则浮点数类型为java.lang.BigDecimal
。尽管如此,在一些接受参数为float
或double
的方法中,依然可以使用BigDecimal
类型作为参数传递。
当数值过长的时候,可以使用_
对数字进行分组,以使阅读更加简洁明了。eg:
- long creditCardNumber = 1234_5678_9012_3456L
- long socialSecurityNumbers = 999_99_9999L
- double monetaryAmount = 12_345_132.12
- long hexBytes = 0xFF_EC_DE_5E
- long hexWords = 0xFFEC_DE5E
- long maxLong = 0x7fff_ffff_ffff_ffffL
- long alsoMaxLong = 9_223_372_036_854_775_807L
- long bytes = 0b11010010_01101001_10010100_10010010
可以通过使用后缀来指定数字类型
G
或g
L
或l
I
或i
G
或g
D
或d
F
或f
eg:
- assert 42I == new Integer('42')
- assert 42i == new Integer('42') // lowercase i more readable
- assert 123L == new Long("123") // uppercase L more readable
- assert 2147483648 == new Long('2147483648') // Long type used, value too large for an Integer
- assert 456G == new BigInteger('456')
- assert 456g == new BigInteger('456')
- assert 123.45 == new BigDecimal('123.45') // default BigDecimal type used
- assert 1.200065D == new Double('1.200065')
- assert 1.234F == new Float('1.234')
- assert 1.23E23D == new Double('1.23E23')
- assert 0b1111L.class == Long // binary
- assert 0xFFi.class == Integer // hexadecimal
- assert 034G.class == BigInteger // octal
布尔类型是一种特殊的类型用于判断对或错:true
或false
。Groovy有一套特别的规则用于强制将non-boolean类型转换为bollean类型。
Groovy中没有定义自己的List类型,使用的是java.util.List
类型。通过一对[]
包括,里面的元素以,
分隔来定义一个List。默认情况下,创建的List的类型为java.util.ArrayList
。eg:
- def numbers = [1, 2, 3]
-
- assert numbers instanceof List
- assert numbers.size() == 3
List中元素可以是不同类型:
def heterogeneous = [1, "a", true]
通过使用as
操作符可以强制指定List的类型,或者在声明List变量时强制指定类型。eg:
- def arrayList = [1, 2, 3]
- assert arrayList instanceof java.util.ArrayList
-
- def linkedList = [2, 3, 4] as LinkedList
- assert linkedList instanceof java.util.LinkedList
-
- LinkedList otherLinked = [3, 4, 5]
- assert otherLinked instanceof java.util.LinkedList
可以使用[]
获取List中的元素,可以使用<<
向list末尾追加元素。
- 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']
Groovy定义数组的方式和定义list的方式一样,只不过声明时需要制定类型,或者通过as
来强制制定类型为Array。
- String[] arrStr = ['Ananas', 'Banana', 'Kiwi']
-
- assert arrStr instanceof String[]
- assert !(arrStr instanceof List)
-
- def numArr = [1, 2, 3] as int[]
-
- assert numArr instanceof int[]
- assert numArr.size() == 3
-
- //多维数组
-
- def matrix3 = new Integer[3][3]
- assert matrix3.size() == 3
- Integer[][] matrix2
- matrix2 = [[1, 2], [3, 4]]
- assert matrix2 instanceof Integer[][]
Groovy不支持Java数组的初始化方式。
Map定义方式为:使用[]
包括,里面的元素为key/value的形式,key和value以:
分隔,每一对key/value以逗号分隔。Groovy穿件的map默认类型为java.util.LinkedHashMap
。eg:
- 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
Map中通过[key]
或.key
的方式来获取key对应的value。如果key不存在,则返回null。
当我们使用数字作为key时,这个数字可以明确的认为是数字,并不是Groovy根据数字创建了一个字符串。但是如果以一个变量作为key的话,需要将变量用()
包裹起来,否则key为变量,而不是变量所代表的值。eg:
- def key = 'name'
- def person = [key: 'Guillaume'] // key实际上为"key"
-
- assert !person.containsKey('name')
- assert person.containsKey('key')
-
- person = [(key): 'Guillaume'] // key实际上为"name"
-
- assert person.containsKey('name')
- assert !person.containsKey('key')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。