groovy语法
Posted chinago
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了groovy语法相关的知识,希望对你有一定的参考价值。
句法
本章介绍Groovy编程语言的语法。语言的语法源自Java语法,但使用Groovy的特定构造对其进行了增强,并允许某些简化。
1.评论
1.1。单行评论
单行注释以行开头,//
可以在行中的任何位置找到。//
直到行尾的字符被视为注释的一部分。
// a standalone single line comment
println "hello" // a comment till the end of the line
1.2。多行评论
多行注释以行开头,/*
可以在行中的任何位置找到。以下字符/*
将被视为注释的一部分,包括换行符,直到第一个*/
结束注释。因此,多行注释可以放在语句的末尾,甚至可以放在语句中。
/* a standalone multiline comment
spanning two lines */
println "hello" /* a multiline comment starting
at the end of a statement */
println 1 /* one */ + 2 /* two */
1.3。GroovyDoc评论
与多行注释类似,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相同的标记。
1.4。Shebang线
除了单行注释之外,还有一个特殊的行注释,通常称为UNIX系统可以理解的shebang行,它允许脚本直接从命令行运行,只要您已经安装了Groovy发行版并且该groovy
命令可用于PATH
。
#!/usr/bin/env groovy
println "Hello from the shebang line"
该# 字符必须是文件的第一个字符。任何缩进都会产生编译错误。 |
2.关键词
以下列表表示Groovy语言的所有关键字:
如 |
断言 |
打破 |
案件 |
抓住 |
类 |
常量 |
继续 |
高清 |
默认 |
做 |
其他 |
枚举 |
扩展 |
假 |
最后 |
对于 |
去 |
如果 |
器物 |
进口 |
在 |
的instanceof |
接口 |
新 |
空值 |
包 |
返回 |
超 |
开关 |
这个 |
扔 |
投 |
特征 |
真正 |
尝试 |
而 |
3.标识符
3.1。普通标识符
标识符以字母,美元或下划线开头。他们不能以数字开头。
一封信可以在以下范围内:
-
‘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
3.2。带引号的标识符
带引号的标识符出现在虚线表达式的点后面。例如,表达式的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"
4.字符串
文本文字以称为字符串的字符串的形式表示。Groovy允许您实例化java.lang.String
对象,以及GStrings(groovy.lang.GString
),它们在其他编程语言中也称为插值字符串。
4.1。单引号字符串
单引号字符串是由单引号括起来的一系列字符:
‘a single quoted string‘
单引号字符串是普通的java.lang.String ,不支持插值。 |
4.2。字符串连接
所有Groovy字符串都可以与+
运算符连接:
assert ‘ab‘ == ‘a‘ + ‘b‘
4.3。三重单引号字符串
三重单引号字符串是由单引号三元组包围的一系列字符:
‘‘‘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(‘
‘)
4.3.1。逃避特殊字符
您可以使用反斜杠字符转义单引号,以避免终止字符串文字:
‘an escaped single quote: ‘ needs a backslash‘
你可以使用双反斜杠来逃避转义字符本身:
‘an escaped escape character: \ needs a double backslash‘
一些特殊字符也使用反斜杠作为转义字符:
逃脱序列 | 字符 |
---|---|
‘ t‘ |
制表 |
‘ B‘ |
退格 |
‘ n‘ |
新队 |
‘ r‘ |
回车 |
‘F‘ |
换页符 |
‘\‘ |
反斜线 |
‘‘” |
单引号(单引号和三引号字符串) |
‘“‘ |
双引号(双引号和三引号双引号) |
4.3.2。Unicode转义序列
对于键盘上不存在的字符,可以使用unicode转义序列:反斜杠,后跟“u”,然后是4个十六进制数字。
例如,欧元货币符号可以表示为:
‘The Euro currency symbol: u20AC‘
4.4。双引号字符串
双引号字符串是由双引号括起来的一系列字符:
"a double quoted string"
java.lang.String 如果没有插值表达式, 双引号字符串是普通的,但如果存在插值则是groovy.lang.GString 实例。 |
要转义双引号,可以使用反斜杠字符:“双引号:”“。 |
4.4.1。字符串插值
除了单引号和三引号字符串之外,任何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}"
4.4.2。插值闭包表达式的特例
到目前为止,我们已经看到我们可以在${}
占位符内插入任意表达式,但是闭包表达式有一个特殊的情况和符号。当占位符包含箭头时${→}
,表达式实际上是一个闭包表达式 - 您可以将其视为一个封闭,前面有一个美元:
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时调用闭包,从而生成包含新数字值的更新字符串。 |
带有多个参数的嵌入式闭包表达式将在运行时生成异常。仅允许具有零个或一个参数的闭包。 |
4.4.3。与Java的互操作性
当一个方法(无论是用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。 |
4.4.4。GString和String hashCodes
尽管可以使用插值字符串代替普通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值 |
4.5。三重双引号字符串
三重双引号字符串的行为类似于双引号字符串,另外它们是多行的,就像三重单引号字符串一样。
def name = ‘Groovy‘
def template = """
Dear Mr ${name},
You‘re the winner of the lottery!
Yours sincerly,
Dave
"""
assert template.toString().contains(‘Groovy‘)
双引号和单引号都不需要在三重双引号字符串中进行转义。 |
4.6。Slashy string
除了通常引用的字符串之外,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(‘
‘)
Slashy字符串也可以插值(即GString):
def color = ‘blue‘
def interpolatedSlashy = /a ${color} car/
assert interpolatedSlashy == ‘a blue car‘
有一些问题需要注意。
空的slashy字符串不能用双正斜杠表示,因为Groovy解析器将其理解为行注释。这就是为什么以下断言实际上不会编译,因为它看起来像一个非终止语句:
assert ‘‘ == //
由于slashy字符串的设计主要是为了使regexp变得更容易,所以GStrings中的一些错误就像$() slashy字符串一样。 |
4.7。美元邋string的字符串
美元贬值字符串是多行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) }
4.8。字符串摘要表
字符串名称 |
字符串语法 |
内插 |
多行 |
逃避角色 |
单引号 |
|
|
||
三重单引号 |
|
|
||
双引号 |
|
|
||
三倍双引号 |
|
|
||
Slashy |
|
|
||
美元贬值 |
|
|
4.9。人物
与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)更有趣。 |
5.数字
Groovy支持不同类型的整数文字和十进制文字,由通常Number
的Java类型支持。
5.1。积分文字
整数文字类型与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
5.1.1。替代的非基础10表示
数字也可以用二进制,八进制,十六进制和十进制数表示。
二进制文字
二进制数字以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
5.2。十进制文字
十进制文字类型与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
作为参数类型。
十进制数不能使用二进制,八进制或十六进制表示来表示。 |
5.3。文字中的下划线
在编写长字面数字时,更难以弄清楚某些数字是如何组合在一起的,例如成千上万的单词组等。通过允许您在数字文字中放置下划线,更容易发现这些组:
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
5.4。数字类型后缀
我们可以通过给出后缀(见下表)(大写或小写)来强制一个数字(包括二进制,八进制和十六进制)具有特定类型。
类型 | 后缀 |
---|---|
的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
5.5。数学运算
虽然稍后会介绍运算符,但讨论数学运算的行为以及它们的结果类型是很重要的。
除了分区和功率二进制操作(如下所述),
-
之间的二进制运算
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中,不像你必须使用显式的方法对这些数字操作。 |
5.5.1。除法运算符的情况
所述除法运算符/
(并/=
用于划分和分配)产生double
结果如果操作数是一float
或double
,和BigDecimal
否则结果(当两个操作数都是一体型的任意组合short
,char
,byte
,int
,long
, BigInteger
或BigDecimal
)。
BigDecimal
分割与所执行的divide()
,如果划分是确切的方法(即,产生了可在相同的精度和分的范围内表示的结果),或使用MathContext
与精度 最大的两个操作数的精度加上一个额外的精度的10和规模 最大的10和最大操作数规模的。
对于像Java中的整数除法,您应该使用该intdiv() 方法,因为Groovy不提供专用的整数除法运算符符号。 |
5.5.2。电力运营商的情况
动力操作由**
操作员表示,有两个参数:基数和指数。功率操作的结果取决于其操作数和操作的结果(特别是如果结果可以表示为整数值)。
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
6.布尔
7.列表
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
定义数字列表列表 | |
访问最顶层列表的第二个元素,以及内部列表的第一个元素 |
8.数组
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闭包的符号误解。 |
9.地图
有时在其他语言中称为字典或关联数组,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 以前那样包含密钥 |
以上是关于groovy语法的主要内容,如果未能解决你的问题,请参考以下文章