// a standalone single line comment
println "hello" // a comment till the end of the line
标签:nbsp 自动 ret 本质 参数传递 删除 哈希 more 出现
本章介绍Groovy编程语言的语法。语言的语法源自Java语法,但使用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注释行后面的行可以选择以星号开头*。这些评论与:
类型定义(类,接口,枚举,注释),
字段和属性定义
方法定义
虽然编译器不会抱怨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}"
}
}
GroovyDoc遵循与Java自己的JavaDoc相同的约定。因此,您将能够使用与JavaDoc相同的标记。
除了单行注释之外,还有一个特殊的行注释,通常称为UNIX系统可以理解的shebang行,它允许脚本直接从命令行运行,只要您已经安装了Groovy发行版并且该groovy命令可用于PATH。
#!/usr/bin/env groovy
println "Hello from the shebang line"
该#字符必须是文件的第一个字符。任何缩进都会产生编译错误。 |
以下列表表示Groovy语言的所有关键字:
|
如 |
断言 |
打破 |
案件 |
|
抓住 |
类 |
常量 |
继续 |
|
高清 |
默认 |
做 |
其他 |
|
枚举 |
扩展 |
假 |
最后 |
|
对于 |
去 |
如果 |
器物 |
|
进口 |
在 |
的instanceof |
接口 |
|
新 |
空值 |
包 |
返回 |
|
超 |
开关 |
这个 |
扔 |
|
投 |
特征 |
真正 |
尝试 |
|
而 |
标识符以字母,美元或下划线开头。他们不能以数字开头。
一封信可以在以下范围内:
‘a‘到‘z‘(小写ascii字母)
‘A‘到‘Z‘(大写ascii字母)
‘\ u00C0‘到‘\ u00D6‘
‘\ u00D8‘到‘\ u00F6‘
‘\ u00F8‘到‘\ u00FF‘
‘\ u0100‘到‘\ uFFFE‘
然后跟随字符可以包含字母和数字。
以下是有效标识符的一些示例(此处为变量名称):
def name
def item3
def with_underscore
def $dollarStart
但以下是无效的标识符:
def 3tier
def a+b
def a#b
关注点后,所有关键字也都是有效的标识符:
foo.as
foo.assert
foo.break
foo.case
foo.catch
带引号的标识符出现在虚线表达式的点后面。例如,表达式的name一部分person.name可以用person."name"或引用person.‘name‘。当某些标识符包含Java语言规范禁止但在引用时Groovy允许的非法字符时,这一点尤其有趣。例如,短划线,空格,感叹号等字符。
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提供了不同的字符串文字。点后实际允许所有类型的字符串:
map.‘single quote‘
map."double quote"
map.‘‘‘triple single quote‘‘‘
map."""triple double quote"""
map./slashy string/
map.$/dollar slashy string/$
普通字符串和Groovy的GStrings(插值字符串)之间存在差异,因为在后一种情况下,插值将插入到最终字符串中以评估整个标识符:
def firstname = "Homer"
map."Simpson-${firstname}" = "Homer Simpson"
assert map.‘Simpson-Homer‘ == "Homer Simpson"
文本文字以称为字符串的字符串的形式表示。Groovy允许您实例化java.lang.String对象,以及GStrings(groovy.lang.GString),它们在其他编程语言中也称为插值字符串。
单引号字符串是由单引号括起来的一系列字符:
‘a single quoted string‘
单引号字符串是普通的java.lang.String,不支持插值。 |
所有Groovy字符串都可以与+运算符连接:
assert ‘ab‘ == ‘a‘ + ‘b‘
三重单引号字符串是由单引号三元组包围的一系列字符:
‘‘‘a triple single quoted string‘‘‘
三重单引号字符串是普通的java.lang.String,不支持插值。 |
三重单引号字符串是多行的。您可以跨越行边界跨越字符串的内容,而无需将字符串拆分为多个部分,而不使用连接或换行转义字符:
def aMultilineString = ‘‘‘line one
line two
line three‘‘‘
如果您的代码是缩进的,例如在类方法的主体中,则字符串将包含缩进的空格。Groovy开发工具包包含使用该String#stripIndent()方法去除缩进的方法,以及使用String#stripMargin()分隔符来识别要从字符串开头删除的文本的方法。
创建字符串时如下:
def startingAndEndingWithANewline = ‘‘‘
line one
line two
line three
‘‘‘
您会注意到结果字符串包含换行符作为第一个字符。可以通过使用反斜杠转义换行来删除该字符:
def strippedFirstNewline = ‘‘‘line one
line two
line three
‘‘‘
assert !strippedFirstNewline.startsWith(‘\n‘)
您可以使用反斜杠字符转义单引号,以避免终止字符串文字:
‘an escaped single quote: \‘ needs a backslash‘
你可以使用双反斜杠来逃避转义字符本身:
‘an escaped escape character: \\ needs a double backslash‘
一些特殊字符也使用反斜杠作为转义字符:
| 逃脱序列 | 字符 |
|---|---|
|
‘\ t‘ |
制表 |
|
‘\ B‘ |
退格 |
|
‘\ n‘ |
新队 |
|
‘\ r‘ |
回车 |
|
‘\F‘ |
换页符 |
|
‘\\‘ |
反斜线 |
|
‘\‘” |
单引号(单引号和三引号字符串) |
|
‘\“‘ |
双引号(双引号和三引号双引号) |
对于键盘上不存在的字符,可以使用unicode转义序列:反斜杠,后跟“u”,然后是4个十六进制数字。
例如,欧元货币符号可以表示为:
‘The Euro currency symbol: \u20AC‘
双引号字符串是由双引号括起来的一系列字符:
"a double quoted string"
java.lang.String如果没有插值表达式, 双引号字符串是普通的,但如果存在插值则是groovy.lang.GString实例。 |
| 要转义双引号,可以使用反斜杠字符:“双引号:\”“。 |
除了单引号和三引号字符串之外,任何Groovy表达式都可以在所有字符串文字中进行插值。插值是在对字符串求值时将字符串中的占位符替换为其值的行为。占位符表达式由虚线表达式包围${}或前缀$。当GString被传递给通过调用toString()该表达式将String作为参数的方法时,占位符内的表达式值将被计算为其字符串表示形式。
这里,我们有一个字符串,其中占位符引用了一个局部变量:
def name = ‘Guillaume‘ // a plain string
def greeting = "Hello ${name}"
assert greeting.toString() == ‘Hello Guillaume‘
但是任何Groovy表达式都是有效的,正如我们在本例中可以看到的算术表达式:
def sum = "The sum of 2 and 3 equals ${2 + 3}"
assert sum.toString() == ‘The sum of 2 and 3 equals 5‘
不仅在${}占位符之间允许表达式,而且语句也是如此。但是,声明的价值恰到好处null。因此,如果在该占位符中插入了多个语句,则最后一个语句应以某种方式返回要插入的有意义值。例如,“1和2的总和等于$ {def a = 1; def b = 2; a + b}”是支持的并且按预期工作但是一个好的做法通常是坚持GString占位符中的简单表达式。 |
除了${}占位符之外,我们还可以使用$前缀为虚线表达式的单个符号:
def person = [name: ‘Guillaume‘, age: 36]
assert "$person.name is $person.age years old" == ‘Guillaume is 36 years old‘
但是,只有形式的虚线表达a.b,a.b.c等等,都是有效的,但会包含类似的方法调用,闭包大括号,或算术运算符括号表达式将是无效的。给定以下数字的变量定义:
def number = 3.14
以下语句将抛出一个groovy.lang.MissingPropertyException因为Groovy认为您正在尝试访问该toString数字的属性,该属性不存在:
shouldFail(MissingPropertyException) {
println "$number.toString()"
}
您可以"$number.toString()"将解析器视为解释为"${number.toString}()"。 |
如果你需要在GString中转义$或${}占位符,使它们看起来没有插值,你只需要使用\反斜杠字符来逃避美元符号:
assert ‘${name}‘ == "\${name}"
到目前为止,我们已经看到我们可以在${}占位符内插入任意表达式,但是闭包表达式有一个特殊的情况和符号。当占位符包含箭头时${→},表达式实际上是一个闭包表达式 - 您可以将其视为一个封闭,前面有一个美元:
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参数,你可以使用<<leftShift运算符追加内容。在任何一种情况下,两个占位符都是嵌入式封闭。 |
从外观上看,它看起来像是一种定义要插入的表达式的更冗长的方式,但是闭包与单纯的表达式相比具有一个有趣的优势:懒惰的评估。
让我们考虑以下示例:
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"
assert lazyGString == "value == 2"
我们定义一个number包含的变量1,然后我们在两个GStrings内插入,作为一个表达式eagerGString和作为闭包lazyGString。 |
|
我们希望结果字符串包含相同的字符串值1 eagerGString。 |
|
同样的 lazyGString |
|
| 然后我们将变量的值更改为新数字 | |
| 使用普通插值表达式,该值实际上是在创建GString时绑定的。 | |
| 但是使用闭包表达式时,会在每次将GString强制转换为String时调用闭包,从而生成包含新数字值的更新字符串。 |
| 带有多个参数的嵌入式闭包表达式将在运行时生成异常。仅允许具有零个或一个参数的闭包。 |
当一个方法(无论是用Java还是Groovy实现)需要a java.lang.String,但是我们传递一个groovy.lang.GString实例时,toString()会自动且透明地调用GString 的方法。
String takeString(String message) {
assert message instanceof String
return message
}
def message = "The message is ${‘hello‘}"
assert message instanceof GString
def result = takeString(message)
assert result instanceof String
assert result == ‘The message is hello‘
| 我们创建一个GString变量 | |
| 我们仔细检查它是GString的一个实例 | |
| 然后我们将该GString传递给一个以String作为参数的方法 | |
该takeString()方法的签名明确表示其唯一参数是String |
|
| 我们还验证参数确实是String而不是GString。 |
尽管可以使用插值字符串代替普通Java字符串,但它们以特定方式与字符串不同:它们的hashCodes不同。普通Java字符串是不可变的,而GString的结果字符串表示形式可能会有所不同,具体取决于其内插值。即使对于相同的结果字符串,GStrings和Strings也没有相同的hashCode。
assert "one: ${1}".hashCode() != "one: 1".hashCode()
应该避免使用GString作为Map键的具有不同hashCode值的GString和Strings,尤其是当我们尝试使用String而不是GString检索关联值时。
def key = "a"
def m = ["${key}": "letter ${key}"]
assert m["a"] == null
| 使用初始对创建映射,其键是GString | |
| 当我们尝试使用String键获取值时,我们将找不到它,因为Strings和GString具有不同的hashCode值 |
三重双引号字符串的行为类似于双引号字符串,另外它们是多行的,就像三重单引号字符串一样。
def name = ‘Groovy‘
def template = """
Dear Mr ${name},
You‘re the winner of the lottery!
Yours sincerly,
Dave
"""
assert template.toString().contains(‘Groovy‘)
| 双引号和单引号都不需要在三重双引号字符串中进行转义。 |
除了通常引用的字符串之外,Groovy还提供了/用作分隔符的字符串。Slashy字符串对于定义正则表达式和模式特别有用,因为不需要转义反斜杠。
一个slashy字符串的示例:
def fooPattern = /.*foo.*/
assert fooPattern == ‘.*foo.*‘
只需使用反斜杠转义正斜杠:
def escapeSlash = /The character \/ is a forward slash/
assert escapeSlash == ‘The character / is a forward slash‘
Slashy字符串是多行的:
def multilineSlashy = /one
two
three/
assert multilineSlashy.contains(‘\n‘)
Slashy字符串也可以插值(即GString):
def color = ‘blue‘
def interpolatedSlashy = /a ${color} car/
assert interpolatedSlashy == ‘a blue car‘
有一些问题需要注意。
空的slashy字符串不能用双正斜杠表示,因为Groovy解析器将其理解为行注释。这就是为什么以下断言实际上不会编译,因为它看起来像一个非终止语句:
assert ‘‘ == //
由于slashy字符串的设计主要是为了使regexp变得更容易,所以GStrings中的一些错误就像$()slashy字符串一样。 |
美元贬值字符串是多行GStrings,以开头$/和结尾分隔/$。逃脱的角色是美元符号,它可以逃避另一美元或正斜线。但是美元和正斜线都不需要被转义,除了逃避一个字符串子序列的美元,它会像GString占位符序列一样开始,或者如果你需要转义一个序列,它会像一个结束的美元斜线字符串分隔符一样开始。
这是一个例子:
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 opening dollar slashy
$/$$ escaped closing dollar slashy
/$
assert [
‘Guillaume‘,
‘April, 1st‘,
‘$ dollar sign‘,
‘$ escaped dollar sign‘,
‘\\ backslash‘,
‘/ forward slash‘,
‘/ escaped forward slash‘,
‘$/ escaped opening dollar slashy‘,
‘/$ escaped closing dollar slashy‘
].every { dollarSlashy.contains(it) }
|
字符串名称 |
字符串语法 |
内插 |
多行 |
逃避角色 |
|
单引号 |
|
|
||
|
三重单引号 |
|
|
||
|
双引号 |
|
|
||
|
三倍双引号 |
|
|
||
|
Slashy |
|
|
||
|
美元贬值 |
|
|
与Java不同,Groovy没有明确的字符文字。但是,您可以通过三种不同的方式明确将Groovy字符串设置为实际字符:
char c1 = ‘A‘
assert c1 instanceof Character
def c2 = ‘B‘ as char
assert c2 instanceof Character
def c3 = (char)‘C‘
assert c3 instanceof Character
通过指定char类型声明保存字符的变量时显式 |
|
通过与as操作员使用类型强制 |
|
| 通过使用强制转换为char操作 |
| 当字符保存在变量中时, 第一个选项1很有趣,而当必须将char值作为方法调用的参数传递时,其他两个(2和3)更有趣。 |
Groovy支持不同类型的整数文字和十进制文字,由通常Number的Java类型支持。
整数文字类型与Java中相同:
byte
char
short
int
long
java.lang.BigInteger
您可以使用以下声明创建这些类型的整数:
// 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
以及负数:
def na = -1
assert na instanceof Integer
// Integer.MIN_VALUE
def nb = -2147483648
assert nb instanceof Integer
// Integer.MIN_VALUE - 1
def nc = -2147483649
assert nc instanceof Long
// Long.MIN_VALUE
def nd = -9223372036854775808
assert nd instanceof Long
// Long.MIN_VALUE - 1
def ne = -9223372036854775809
assert ne instanceof BigInteger
数字也可以用二进制,八进制,十六进制和十进制数表示。
二进制数字以0b前缀开头:
int xInt = 0b10101111
assert xInt == 175
short xShort = 0b11001001
assert xShort == 201 as short
byte xByte = 0b11
assert xByte == 3 as byte
long xLong = 0b101101101101
assert xLong == 2925l
BigInteger xBigInteger = 0b111100100001
assert xBigInteger == 3873g
int xNegativeInt = -0b10101111
assert xNegativeInt == -175
八进制数以典型格式指定,0后跟八进制数字。
int xInt = 077
assert xInt == 63
short xShort = 011
assert xShort == 9 as short
byte xByte = 032
assert xByte == 26 as byte
long xLong = 0246
assert xLong == 166l
BigInteger xBigInteger = 01111
assert xBigInteger == 585g
int xNegativeInt = -077
assert xNegativeInt == -63
十六进制数以典型格式指定,0x后跟十六进制数字。
int xInt = 0x77
assert xInt == 119
short xShort = 0xaa
assert xShort == 170 as short
byte xByte = 0x3a
assert xByte == 58 as byte
long xLong = 0xffff
assert xLong == 65535l
BigInteger xBigInteger = 0xaaaa
assert xBigInteger == 43690g
Double xDouble = new Double(‘0x1.0p0‘)
assert xDouble == 1.0d
int xNegativeInt = -0x77
assert xNegativeInt == -119
十进制文字类型与Java中的相同:
float
double
java.lang.BigDecimal
您可以使用以下声明创建这些类型的十进制数:
// primitive types
float f = 1.234
double d = 2.345
// infinite precision
BigDecimal bd = 3.456
小数可以使用指数,用e或E指数字母,后跟一个可选的标志,以及代表指数一个整数:
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选择java.lang.BigDecimal十进制数字类型。此外,无论float和double支持,但需要一个明确的类型声明,类型强制或后缀。即使BigDecimal是十进制数的默认值,也可以在方法或闭包中接受这样的文字float或double作为参数类型。
| 十进制数不能使用二进制,八进制或十六进制表示来表示。 |
在编写长字面数字时,更难以弄清楚某些数字是如何组合在一起的,例如成千上万的单词组等。通过允许您在数字文字中放置下划线,更容易发现这些组:
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
我们可以通过给出后缀(见下表)(大写或小写)来强制一个数字(包括二进制,八进制和十六进制)具有特定类型。
| 类型 | 后缀 |
|---|---|
|
的BigInteger |
|
|
长 |
|
|
整数 |
|
|
BigDecimal的 |
|
|
双 |
|
|
浮动 |
|
例子:
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
虽然稍后会介绍运算符,但讨论数学运算的行为以及它们的结果类型是很重要的。
除了分区和功率二进制操作(如下所述),
之间的二进制运算byte,char,short和int结果int
二进制运算涉及long用byte,char,short和int导致long
二进制操作涉及BigInteger和任何其他整数类型的结果BigInteger
涉及二进制运算BigDecimal与byte,char,short,int并BigInteger导致BigDecimal
之间的二进制运算float,double并BigDecimal导致double
两者之间的二进制运算BigDecimal导致BigDecimal
下表总结了这些规则:
| 字节 | 烧焦 | 短 | INT | 长 | 的BigInteger | 浮动 | 双 | BigDecimal的 | |
|---|---|---|---|---|---|---|---|---|---|
|
字节 |
INT |
INT |
INT |
INT |
长 |
的BigInteger |
双 |
双 |
BigDecimal的 |
|
烧焦 |
INT |
INT |
INT |
长 |
的BigInteger |
双 |
双 |
BigDecimal的 |
|
|
短 |
INT |
INT |
长 |
的BigInteger |
双 |
双 |
BigDecimal的 |
||
|
INT |
INT |
长 |
的BigInteger |
双 |
双 |
BigDecimal的 |
|||
|
长 |
长 |
的BigInteger |
双 |
双 |
BigDecimal的 |
||||
|
的BigInteger |
的BigInteger |
双 |
双 |
BigDecimal的 |
|||||
|
浮动 |
双 |
双 |
双 |
||||||
|
双 |
双 |
双 |
|||||||
|
BigDecimal的 |
BigDecimal的 |
由于Groovy的操作符重载,通常的算术运算符与工作以及BigInteger和BigDecimal在Java中,不像你必须使用显式的方法对这些数字操作。 |
所述除法运算符/(并/=用于划分和分配)产生double结果如果操作数是一float或double,和BigDecimal否则结果(当两个操作数都是一体型的任意组合short,char,byte,int,long, BigInteger或BigDecimal)。
BigDecimal分割与所执行的divide(),如果划分是确切的方法(即,产生了可在相同的精度和分的范围内表示的结果),或使用MathContext与精度 最大的两个操作数的精度加上一个额外的精度的10和规模 最大的10和最大操作数规模的。
对于像Java中的整数除法,您应该使用该intdiv()方法,因为Groovy不提供专用的整数除法运算符符号。 |
动力操作由**操作员表示,有两个参数:基数和指数。功率操作的结果取决于其操作数和操作的结果(特别是如果结果可以表示为整数值)。
Groovy的电源操作使用以下规则来确定结果类型:
如果指数是十进制值
如果结果可以表示为a Integer,则返回一个Integer
否则,如果结果可以表示为a Long,则返回aLong
否则返回一个 Double
如果指数是一个整数值
如果指数严格为负,则返回a Integer,Long或者Double如果结果值适合该类型
如果指数是正数或零
如果base是a BigDecimal,则返回BigDecimal结果值
如果base是a BigInteger,则返回BigInteger结果值
如果base是a Integer,则返回a,Integer如果结果值适合它,否则aBigInteger
如果base是a Long,则返回a,Long如果结果值适合它,否则aBigInteger
我们可以用几个例子说明这些规则:
// base and exponent are ints and the result can be represented by an Integer
assert 2 ** 3 instanceof Integer // 8
assert 10 ** 9 instanceof Integer // 1_000_000_000
// the base is a long, so fit the result in a Long
// (although it could have fit in an Integer)
assert 5L ** 2 instanceof Long // 25
// the result can‘t be represented as an Integer or Long, so return a BigInteger
assert 100 ** 10 instanceof BigInteger // 10e20
assert 1234 ** 123 instanceof BigInteger // 170515806212727042875...
// the base is a BigDecimal and the exponent a negative int
// but the result can be represented as an Integer
assert 0.5 ** -2 instanceof Integer // 4
// the base is an int, and the exponent a negative float
// but again, the result can be represented as an Integer
assert 1 ** -0.3f instanceof Integer // 1
// the base is an int, and the exponent a negative int
// but the result will be calculated as a Double
// (both base and exponent are actually converted to doubles)
assert 10 ** -1 instanceof Double // 0.1
// the base is a BigDecimal, and the exponent is an int, so return a BigDecimal
assert 1.2 ** 10 instanceof BigDecimal // 6.1917364224
// the base is a float or double, and the exponent is an int
// but the result can only be represented as a Double value
assert 3.4f ** 5 instanceof Double // 454.35430372146965
assert 5.6d ** 2 instanceof Double // 31.359999999999996
// the exponent is a decimal value
// and the result can only be represented as a Double value
assert 7.8 ** 1.9 instanceof Double // 49.542708423868476
assert 2 ** 0.1f instanceof Double // 1.0717734636432956
Groovy使用逗号分隔的值列表(用方括号括起来)来表示列表。Groovy列表是普通的JDK java.util.List,因为Groovy没有定义自己的集合类。java.util.ArrayList默认情况下,定义列表文字时使用的具体列表实现,除非您决定另行指定,我们将在后面看到。
def numbers = [1, 2, 3]
assert numbers instanceof List
assert numbers.size() == 3
| 我们定义一个由逗号分隔的列表编号,并用方括号括起来,然后我们将该列表分配给一个变量 | |
该列表是Java java.util.List接口的一个实例 |
|
可以使用size()方法查询列表的大小,并显示我们的列表包含3个元素 |
在上面的示例中,我们使用了同类列表,但您也可以创建包含异构类型值的列表:
def heterogeneous = [1, "a", true]
| 这里的列表包含数字,字符串和布尔值 |
我们提到默认情况下,列表文字实际上是实例java.util.ArrayList,但是可以为我们的列表使用不同的支持类型,这要归功于对as运算符使用类型强制,或者使用变量的显式类型声明:
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
我们使用强制as操作符来明确请求java.util.LinkedList实现 |
|
我们可以说保存列表文字的变量是类型的 java.util.LinkedList |
您可以使用[]下标运算符(用于读取和设置值)访问列表元素,使用正索引或负索引来访问列表末尾的元素以及范围,并使用<<leftShift运算符将元素附加到一个列表:
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‘]
| 访问列表的第一个元素(从零开始计数) | |
| 使用负索引访问列表的最后一个元素:-1是列表末尾的第一个元素 | |
| 使用赋值为列表的第三个元素设置新值 | |
使用<<leftShift运算符在列表的末尾追加一个元素 |
|
| 一次访问两个元素,返回包含这两个元素的新列表 | |
| 使用范围可以从列表中访问一系列值,从开始到结束元素位置 |
由于列表本质上可以是异构的,因此列表还可以包含其他列表来创建多维列表:
def multi = [[0, 1], [2, 3]]
assert multi[1][0] == 2
| 定义数字列表列表 | |
| 访问最顶层列表的第二个元素,以及内部列表的第一个元素 |
Groovy重用了数组的列表表示法,但是为了制作这样的文字数组,你需要通过强制或类型声明来明确地定义数组的类型。
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
| 使用显式变量类型声明定义字符串数组 | |
| 断言我们创建了一个字符串数组 | |
使用as运算符创建一个int数组 |
|
| 断言我们创建了一个原始int数组 |
您还可以创建多维数组:
def matrix3 = new Integer[3][3]
assert matrix3.size() == 3
Integer[][] matrix2
matrix2 = [[1, 2], [3, 4]]
assert matrix2 instanceof Integer[][]
| 您可以定义新数组的边界 | |
| 或者声明一个数组而不指定其边界 |
对数组元素的访问遵循与列表相同的表示法:
String[] names = [‘Cédric‘, ‘Guillaume‘, ‘Jochen‘, ‘Paul‘]
assert names[0] == ‘Cédric‘
names[2] = ‘Blackdrag‘
assert names[2] == ‘Blackdrag‘
| 检索数组的第一个元素 | |
| 将数组的第三个元素的值设置为新值 |
| Groovy不支持Java的数组初始化表示法,因为花括号可能会被Groovy闭包的符号误解。 |
有时在其他语言中称为字典或关联数组,Groovy具有地图功能。映射将键与值相关联,使用冒号分隔键和值,使用逗号分隔每个键/值对,以及用方括号括起的整个键和值。
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
| 我们定义了一个字符串颜色名称的映射,与它们的十六进制编码的html颜色相关联 | |
我们使用下标表示法来检查与red密钥相关的内容 |
|
| 我们还可以使用属性表示法来断言颜色绿色的十六进制表示 | |
| 类似地,我们可以使用下标符号来添加新的键/值对 | |
或属性表示法,添加yellow颜色 |
| 当使用键的名称时,我们实际上在地图中定义了字符串键。 |
Groovy创建实际上是实例的地图java.util.LinkedHashMap。 |
如果您尝试访问地图中不存在的密钥:
assert colors.unknown == null
您将检索null结果。
在上面的示例中,我们使用了字符串键,但您也可以使用其他类型的值作为键:
def numbers = [1: ‘one‘, 2: ‘two‘]
assert numbers[1] == ‘one‘
在这里,我们使用数字作为键,因为数字可以明确地被识别为数字,因此Groovy不会像我们之前的例子那样创建字符串键。但是考虑一下你要传递一个变量代替键的情况,让该变量的值成为关键:
def key = ‘name‘
def person = [key: ‘Guillaume‘]
assert !person.containsKey(‘name‘)
assert person.containsKey(‘key‘)
在key与相关的‘Guillaume‘名称实际上是"key"字符串,而不是与相关联的值key变 |
|
地图不包含‘name‘密钥 |
|
相反,地图包含一个‘key‘键 |
| 您还可以传递带引号的字符串以及键:[“name”:“Guillaume”]。如果您的密钥字符串不是有效的标识符,那么这是必需的,例如,如果您想创建一个包含哈希的字符串密钥,如:[“street-name”:“Main street”]。 |
当您需要在地图定义中将变量值作为键传递时,必须用括号括起变量或表达式:
person = [(key): ‘Guillaume‘]
assert person.containsKey(‘name‘)
assert !person.containsKey(‘key‘)
这次,我们key用括号括起变量,指示解析器传递变量而不是定义字符串键 |
|
地图确实包含name密钥 |
|
但是地图不像key以前那样包含密钥 |
标签:nbsp 自动 ret 本质 参数传递 删除 哈希 more 出现
原文地址:https://www.cnblogs.com/ChinaGo/p/10200373.html