本章節涵蓋了groovy程式設計語言的文法。groovy語言的文法源自java文法,為groovy增強了特定構造,允許一定程度上的簡化文法。
單行注釋以//開始,在一行中任何位置都可以被發現。//後面的字元,直到一行的末尾都是注釋的一部分。
一個多行注釋以/*開始,在一行中的任何位置都可以發現,/*後面的字元将被視為注釋的一部分,包括換行符,直到第一個*/關閉注釋。
多行注釋可以放在語句的末尾,甚至是在一個語句中。
與多行注釋相似,groovy文檔注釋也是多行的,但是是以/**開始,以*/結尾。第一個groovy文檔注釋後的行,可以以*開始。這些注釋與以下内容關聯:
類型定義 (類, 接口, 枚舉, 注解)
字段和屬性定義
方法定義
盡管編譯器不會抱怨groovy文檔注釋沒有與上述語言元素關聯,你應該在這些語言元素之前使用注釋加上這些構造。
groovy文檔遵循與java文檔相同的約定。是以你能使用與java文檔一樣的标簽。
除單行注釋外,還有一種特殊的行注釋,在unix系統下經常被稱作是事務行,且允許腳本直接從指令行運作,前提是你應将安裝了groovy釋出版,且在path中groovy的指令行是可用的。
#字元必須是檔案的第一個字元。任何縮進都會産生編譯錯誤。
下面清單表示了groovy語言所有的關鍵字
辨別符以字母,美元符号或下劃線開始。不能以一個數字開始。
一個字母可以在以下範圍:
‘a’ 至 ‘z’ (小寫ascii字母)
‘a’ 至 ‘z’ (大寫ascii字母)
‘\u00c0′ 至 ‘\u00d6′
‘\u00d8′ 至 ‘\u00f6′
‘\u00f8′ 至 ‘\u00ff’
‘\u0100′ 至 ‘\ufffe’
後面的字元可以包括字母和數字。
這裡是一些合法辨別符的示例(這裡是變量名稱):
但是以下面展示了一些非法的辨別符:
當在一個點後,所有的關鍵字也是合法的辨別符:
引用辨別符出現在一個點式表達式的點後面。例如,person.name表達式中的name,能通過person.”name”,person.’name’被引用。當某些辨別符包含有java語言規範禁止的非法字元,這是相當有趣的,但被groovy引用所允許。例如,像一個破折号,一個空格,一個感歎号等。
正如我們将在字元串章節看到的,groovy提供了不同的字元串字面量。所有不同類型的字元串都被允許出現在點後面:
普通字元串和groovy的gstrings有一些不同(有插值的字元串),正如在後者的情況下,插入的值被插入到最後的字元串中,以計算整個辨別符:
文本文字以字元鍊的形式表示被稱作字元串。groovy可以讓你執行個體化java.lang.string對象,也可以執行個體化gstring(groovy.lang.gstring),在其他程式設計語言中被稱為插值字元串。
單引号字元串是一系列被單引号包圍的字元。
單引号字元串是普通的java.lang.string,不支援插值。
所有groovy字元串能使用+操作符連接配接:
三單引号字元串是一列被三個單引号包圍的字元:
三單引号字元串是普通的java.lang.string,不支援插值。
三單引号字元串是多行的。你可以使字元串内容跨越行邊界,不需要将字元串分割為一些片段,不需要連接配接,或換行轉義符:
如果你的代碼是縮進的,如類中的方法體,字元串将包括縮進的空格。groovy開發工具包含一些剝離縮進的方法,使用string#stripindent()方法,并使用string#stripmargin()方法,需要一個分隔符來識别文本從一個字元串的開始删除。
當建立一個如下字元串:
你将要注意的是,這個字元串的結果包含一個換行轉義符作為第一個字元。它可以通過使用反斜杠換行符剝離該字元:
你可以使用反斜杠字元轉義單引号,避免終止字元串:
你能使用雙反斜杠來轉義轉義字元自身:
一些特殊字元使用反斜杠作為轉義字元:
對于那些鍵盤不能表示的字元,你能使用unicode轉義序列:一個反斜杠,後面跟着‘u’,然後是4個十六進制的數字。
例如,歐元貨币标志可以使用這個表示:
雙引号字元串是一些列被雙引号包圍的字元:
如果沒有插值表達式,雙引号字元串是普通的java.lang.string,如果插值存在則是groocy.lang.gstring執行個體。
為了轉義一個雙引号,你能使用反斜杠字元:”a double quote: \””。
任何groovy表達式可以在所有字元文本進行插值,除了單引号和三單引号字元串。插值是使用占位符上的字元串計算值替換占位符的操作。占位符表達式是被${}包圍,或字首為$的表達式。當gstring被傳遞給一個帶有一個string參數的方法時,占位符的表達式被計算值,并通過調用表達式的tostring()方法以字元串形式表示。
這裡是一個占位符引用局部變量的字元串:
而且任何groovy表達式是合法的,正如我們在示例中使用算數表達式所見一樣:
不僅任何表達式,實際上也允許${}占位符。語句也是被允許的,但一個語句等效于null。如果有多個語句插入占位符,那麼最後一個語句應該傳回一個有意義的值被插入占位符。例如,”the sum of 1 and 2 is equal to ${def a = 1; def b = 2; a + b}”字元串是被支援的,也能如預期一樣工作,但一個好的實踐是在gstring占位符插入一個簡單的表達式。
除了${}占位符以外,也可以使用$作為表達式字首:
但隻有a.b,a.b.c等形式的字首表達式是合法的,而包含如方法調用的圓括号,閉包的花括号,算術操作符是非法的。給出如下數值變量定義:
如下語句将會抛出groovy.lang.missingpropertyexception,因為groovy相信你在嘗試通路一個不存在數字的tostring屬性:
你可以把”$number.tostring()”用解釋器解釋為”${number.tostring}()”。
如果在gstring中你需要轉義$或${}占位符,使它們不出現插值,那麼你隻需要使用反斜杠字元轉義美元符号:
到目前為止,我們僅僅看到在${}占位符中插入任意表達式,但一個閉包表達式标記的特殊情況。當占位符包括一個箭頭,${->},這表達式實際是一個閉包表達式,你可以把它看做一個前面緊靠美元符号的閉包:
(1)這是一個不攜帶參數的無參閉包
(2)這裡的閉包攜帶一個java.io.stringwrite參數,你能使用<<追加内容。在這兩處,占位符被嵌入閉包。
在外觀上,定義一個表達式被插入看着有一些冗長,但閉包相比表達式有一個有趣的優勢:延遲計算。
讓我們思考如下示例:
(1)我們定義一個包含1的number變量,然後插入兩個gstring之中,在eagergstring中作為表達式,在lazygstring中作為閉包。
(2)我們期望對于eagergstring得到的結果字元串是包含1的相同字元串
(3)lazygstring相似
(4)然後給變量賦一個新值
(5)使用純插值表達式,這值在gstring建立時結合
(6)但使用閉包表達式,gstring被強轉為sring時,閉包被調用,并産生包含新數值的更新字元串。
一個嵌入的閉包表達式,攜帶超過一個參數,那麼在運作時将會産生一個異常。閉包僅僅允許攜帶0個或1個參數。
當一個方法(無論是在java或是groovy中實作)預期需要一個java.lang.string,而我們傳遞了一個groovy.lang.gstring執行個體,gstring的tostring()方法将會被自動透明的調用。
(1)我們建立一個gsring變量
(2)我們仔細檢查gstring執行個體
(3)我們将gstring傳遞個一個攜帶string參數的方法
(4)takestring()明确說明它的唯一參數是一個string
(5)我們也驗證一個參數是string而不是gstring
雖然插值字元串可以代替普通java字元串,它們用一種不同的方式是字元串不同:它們的hashcode是不同的。普通java字元串是不可變的,而一個gstring依賴于插入的值,它的string是可變的。即使有相同的字元串結果,gstring和string也沒有相同的hashcode。
gstring和string有不同的hashcode值,應該避免使用gsring作為map的鍵值,我們使用string代替gstring取出一個關聯值。
(1)map被一個初始化鍵值對建立,其鍵值是gstring
(2)當我們嘗試使用string鍵值擷取值時,我們并沒擷取對應值,因為string和gstring有不同的hashcode
三雙引号字元串與雙引号字元串相同,增加多行,像三單引号字元串一樣。
無論是雙引号還是單引号,在三雙引号字元串中需要被轉義。