// a standalone single line comment println "hello" // a comment till the end of the line
1.註釋
1.1. 單行註釋
1.2. 多行註釋
1.3. GroovyDoc註釋
1.4. Shebang線
2.關鍵詞
3.標識符
3.1. 普通標識符
3.2. 帶引號的標識符
4.字符串
4.1. 單引號字符串
4.2. 字符串鏈接
4.3. 三重單引號字符串
4.3.1. 逃避特殊字符
4.3.2. Unicode轉義序列
4.4. 雙引號字符串
4.4.1. 字符串插值
4.4.2. 插值閉包表達式的特例
4.4.3. 與Java的互操做性
4.4.4. GString和String hashCodes
4.5. 三重雙引號字符串
4.6. Slashy string
4.7. 美圓邋string的字符串
4.8. 字符串摘要表
4.9. 人物
5.數字
5.1. 積分文字
5.1.1. 替代的非基礎10表示
二進制文字
八進制文字
十六進制文字
5.2. 十進制文字
5.3. 文字中的下劃線
5.4. 數字類型後綴
5.5. 數學運算
5.5.1. 除法運算符的狀況
5.5.2. 電力運營商的狀況
6.布爾
7.列表
8.數組
9.maphtml
本章介紹Groovy編程語言的語法。語言的語法源自Java語法,但使用Groovy的特定構造對其進行了加強,並容許某些簡化。java
單行註釋以行開頭,//
能夠在行中的任何位置找到。//
直到行尾的字符被視爲註釋的一部分。正則表達式
// a standalone single line comment println "hello" // a comment till the end of the line
多行註釋以行開頭,/*
能夠在行中的任何位置找到。如下字符/*
將被視爲註釋的一部分,包括換行符,直到第一個*/
結束註釋。所以,多行註釋能夠放在語句的末尾,甚至能夠放在語句中。express
/* 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註釋行後面的行能夠選擇以星號開頭*
。這些註釋與:編程
類型定義(類,接口,枚舉,註釋),api
字段和屬性定義數組
方法定義閉包
雖然編譯器不會抱怨GroovyDoc註釋與上述語言元素沒有關聯,可是你應該在它以前添加帶有註釋的那些結構。oracle
/** * 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語言的全部關鍵字:
Table 1. Keywords
as |
assert |
break |
case |
catch |
class |
const |
continue |
def |
default |
do |
else |
enum |
extends |
false |
finally |
for |
goto |
if |
implements |
import |
in |
instanceof |
interface |
new |
null |
package |
return |
super |
switch |
this |
throw |
throws |
trait |
true |
try |
while
|
標識符以字母,美圓或下劃線開頭。他們不能以數字開頭。
一個字母能夠是如下範圍內:
'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 之前那樣包含密鑰 |