groovy是一門類似于java的語言,在java語言的基礎(chǔ)上,它吸收了很多腳本的特性,比如python,ruby。跟java一樣,每個(gè)groovy文件也是編譯成class文件,在JVM上運(yùn)行。但是相比java,groovy的表達(dá)方式會(huì)更為簡便。最近通過http://groovy.zeroleaf.com/core-syntax.html和http://docs.groovy-lang.org/next/html/documentation/來學(xué)習(xí)groovy。這2篇其實(shí)是差不多的,前一個(gè)是簡單的中文版,是一些groovy的基礎(chǔ)語法。后一個(gè)是英文原版。 我是一個(gè)IDE重度患者,所以選擇使用IntelliJ來學(xué)習(xí)groovy。
下載安裝 sdkman,執(zhí)行下面命令,按照提示安裝即可
$ curl -s http://get.sdkman.io | bash使環(huán)境變量生效
$ source "$HOME/.sdkman/bin/sdkman-init.sh"安裝 Groovy
$ sdk install groovy此時(shí)可以查看groovy版本
192:~ fish$ groovy -vGroovy Version: 2.4.7 JVM: 1.7.0_79 Vendor: Oracle Corporation OS: Mac OS XOK,groovy安裝成功
IntelliJ安裝的時(shí)候默認(rèn)就會(huì)裝上groovy插件,我們只要配置下PRoject sdk和groovy library就好了
1、把groovy庫從.sdkman復(fù)制出來,放到另一個(gè)目錄。我是把groovy文件夾從/Users/fish/.sdkman/candidates/拷貝到/Users/fish/Documents/。 (因?yàn)?sdkman是隱藏文件,所以選擇groovy library的時(shí)候沒辦法點(diǎn)到,所以我才把它拷貝出來,這1步應(yīng)該可以省略的,希望)
2、點(diǎn)擊new project,在左邊列表選擇groovy,右邊project sdk選擇jdk 1.8,groovy Library點(diǎn)擊Create,然后選擇/Users/fish/Documents/groovy/2.4.7,結(jié)果如下所示

3、點(diǎn)擊next 就可以了創(chuàng)建一個(gè)空的groovy工程了 4、在src下new->groovy scr點(diǎn)擊右鍵run就可以看到控制臺上輸出了aaa。 至此,groovy環(huán)境配置完成,以后就可以用IntelliJ來開發(fā)groovy工程了。 好了,可以開始groovy學(xué)習(xí)之旅了
標(biāo)識符(identifiers)以字母, 美元符號$ 或者下劃線開始. 不能以數(shù)字開始,如下所示,注意定義一個(gè)變量要寫def,不用寫明變量類型,因?yàn)間roovy是動(dòng)態(tài)類型的語言。當(dāng)然寫明變量類型也可以,此時(shí)就不用寫def了。
def namedef item3def with_underscoredef $dollarStart//定義了一個(gè)Stringdef sex="male"http://定義了一個(gè)Integerdef age=4//定義了一個(gè)mapdef map = [:]引用標(biāo)識符(quoted identifiers)位于點(diǎn)表達(dá)式(dotted expression)的點(diǎn)號之后.
如下所示可以用map.'a',來訪問map的值,這就是引用標(biāo)識符這里a的引號也可以不用寫,map.a,結(jié)果是一樣的。但是如果像L12不寫引號的話,就是語法錯(cuò)誤,必須加上引號,因?yàn)槔锩嬗锌崭?/定義一個(gè)mapdef map = [:]map."an identifier with a_3_2 space and double quotes" = "ALLOWED"map.'with-dash-signs-and-single-quotes' = "ALLOWED"map.'a'='b'assert map.'a'=='b'assert map.a=='b'//語法錯(cuò)誤//assert map.an identifier with a_3_2 space and double quotes == "ALLOWED"assert map."an identifier with a_3_2 space and double quotes" == "ALLOWED"assert map.'with-dash-signs-and-single-quotes' == "ALLOWED"首先來看下groovy字符串的表現(xiàn)形式,字符串表示的形式多種多樣,如下所示
def map = [:]map.'dollar slashy string'="dollar"http://如下類型字符串作為引用標(biāo)識符都是對的map.'single quote'map."double quote"map.'''triple single quote'''map."""triple double quote"""map./slashy string/assert map.$/dollar slashy string/$=="dollar"http://稍微特殊的GString,也是對的def firstname = "Homer"map."Simson-${firstname}" = "Homer Simson"assert map.'Simson-Homer' == "Homer Simson"Groovy有java.lang.String和groovy.lang.GString兩中字符串對象類型 單引號和三單引號字符串都是String,不支持插值. 雙引號字和三雙引號符串在沒有插入表達(dá)式(interpolated expression)的情況下雙引號字符串為 java.lang.String; 如果有, 則為 groovy.lang.GString 當(dāng)創(chuàng)建如下的字符串:
def startingAndEndingWithANewline = '''line oneline twoline three'''assert strippedFirstNewline.startsWith('/n')字符串插值,可以用${}進(jìn)行插值,如下所示
def name = 'Guillaume' // a_3_2 plain stringdef greeting = "Hello ${name}"http://plaindef greeting2 = "Hello${'girl'}"assert greeting.toString() == 'Hello Guillaume'println(greeting)println(greeting2)當(dāng)一個(gè)方法(不管是在 Java 還是在 Groovy 中實(shí)現(xiàn))期望一個(gè)java.lang.String, 但我們傳入一個(gè) groovy.lang.GString 實(shí)例時(shí), GString 的 toString() 方法會(huì)自動(dòng), 透明地被調(diào)用.
String takeString(String message) { assert message instanceof String return message}def message = "The message is ${'hello'}"assert message instanceof GStringdef result = takeString(message)assert result instanceof Stringassert result == 'The message is hello'盡管插值字符串可以用來代替普通 Java 字符串, 但它們與普通字符串在某一方面還是有區(qū)別的: 即它們的哈希碼(hashCodes)是不一樣的. 普通 Java字符串是不可變的, 然而 GString 的結(jié)果字符串 表示是可變的, 取決于它的插入值. 即使結(jié)果字符串相同, GString 和 String 還是有不同的哈希碼.
//左邊是插值字符串,右邊是普通字符串,hashcode不一致assert "one: ${1}".hashCode() != "one: 1".hashCode()def key = "a"def m = ["${key}": "letter ${key}"]assert m["a"] == null你會(huì)發(fā)現(xiàn)結(jié)果字符串的第一個(gè)字符是一個(gè)換行符. 可以用反斜杠(backslash)轉(zhuǎn)義換行符來移除該字符:
def strippedFirstNewline = '''/line oneline twoline three'''assert !strippedFirstNewline.startsWith('/n')groovy還可以支持unicode字符,如下所示
//歐元貨幣符號def a='The Euro currency symbol: /u20AC'printf(a)結(jié)果The Euro currency symbol: €
與 Java 不同, Groovy 沒有明確的字符字面量. 但是, 你可以通過 3 種不同的方式明確的將 Groovy 字符串轉(zhuǎn)換為字符:
char c1 = 'A'assert c1 instanceof Characterdef c2 = 'B' as charassert c2 instanceof Characterdef c3 = (char)'C'assert c3 instanceof Charactergroovy的List本質(zhì)是java.util.List,但是跟java有些區(qū)別,主要是改了下,讓使用更方便。
創(chuàng)建的時(shí)候卻像java的數(shù)組一樣寫 比如 下邊的numbers不是一個(gè)數(shù)組,而是一個(gè)List(其實(shí)是ArrayList).List元素訪問可以直接用[]訪問List的元素,在java里必須用get()方法,方便了不少,比如L6.List元素訪問可以從后往前,如L7,這個(gè)有點(diǎn)像pythonList增加一個(gè)元素可以用<<這個(gè)操作符//定義了一個(gè)Listdef numbers = [1, 2, 3] assert numbers instanceof List assert numbers.size() == 3 assert numbers[2] == 3assert numbers[-1] == 3//addletters << 'e'groovy的List可以放不同類型的東西,比如下邊的List放了個(gè)int,一個(gè)String,一個(gè)boolean值
def heterogeneous = [1, "a", true]數(shù)組必須指明數(shù)據(jù)類型,訪問數(shù)組元素的方法依然是[],和List一致。
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() == 3assert arrStr[2]=='Kiwi'map實(shí)際數(shù)據(jù)類型是LinkedHashMap,但是創(chuàng)建訪問有點(diǎn)像python的dictionary。
創(chuàng)建的時(shí)候可以用[]訪問的時(shí)候可以用[]或者.創(chuàng)建時(shí)key可以放常量也可以放變量,很有意思,變量用()包含起來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如下所示,上半段代碼person里的,key是字符串“ff”,下半段代碼里key是ff變量,即“name”字符串。
def ff = 'name'def person = [ff: 'Guillaume']assert !person.containsKey('name')assert person.containsKey('ff')person = [(ff): 'Guillaume']assert person.containsKey('name')assert !person.containsKey('ff')groovy會(huì)根據(jù)數(shù)值的大小自動(dòng)分配數(shù)據(jù)類型,
//正數(shù)def a = 1assert a instanceof Integer// Integer.MAX_VALUEdef b = 2147483647assert b instanceof Integer// Integer.MAX_VALUE + 1def c = 2147483648assert c instanceof Long// Long.MAX_VALUEdef d = 9223372036854775807assert d instanceof Long// Long.MAX_VALUE + 1def e = 9223372036854775808assert e instanceof BigInteger//負(fù)數(shù)def na = -1assert na instanceof Integer// Integer.MIN_VALUEdef nb = -2147483648assert nb instanceof Integer// Integer.MIN_VALUE - 1def nc = -2147483649assert nc instanceof Long// Long.MIN_VALUEdef nd = -9223372036854775808assert nd instanceof Long// Long.MIN_VALUE - 1def ne = -9223372036854775809assert ne instanceof BigIntegerString可以直接拿來當(dāng)boolean值使用,空字符串相當(dāng)于false,非空字符串相當(dāng)于true.這里實(shí)際上隱式調(diào)用了asBoolean方法,轉(zhuǎn)換成了boolean,這種隱式轉(zhuǎn)換非常有意義,后面會(huì)看到。
assert (!'foo') == false assert (!'') == true來玩一個(gè)代碼簡化的游戲
if (string!=null && string.length()>0) { result = 'Found'} else { result = 'Not found'}上邊這段代碼可以用三元運(yùn)算符來簡化
result = (string!=null && string.length()>0)?'Found':'Not found'實(shí)際上利用string的boolean轉(zhuǎn)化,我們還可以更簡單,如下所示,其實(shí)上面的代碼我在java里寫過無數(shù)次,如果能直接用 string?'Found':'Not found'來表示真的方便了很多,希望java也能引入類似的語法
我們經(jīng)常寫如下代碼,可以看到重復(fù)寫了user.name
displayName = user.name ? user.name : 'Anonymous' groovy想了個(gè)辦法來簡化,可以如下表示
displayName = user.name ?: 'Anonymous'
?首先有個(gè)groovy類Person,然后看下邊的代碼
class Person { /** 姓名 */ String name /** * 為特定的人創(chuàng)建一個(gè)問候方法. * * @param otherPerson 待問候的人 * @return 問候信息 */ String greet(String otherPerson) { "Hello ${otherPerson}" }}Person[] arrStr = [new Person(), new Person(), null]def person = arrStr[2]def name = person.nameassert name == null這里person會(huì)是null,那么person.name就肯定會(huì)觸發(fā)空指針,groovy定義了一種操作符可以避免空指針,那就是加一個(gè)?代碼如下所示,這么寫代碼就方便多了,不用寫那么多空判斷,但是帶來的隱患就是,最后出了問題,難以排查出原因,不好查哪里是null的源頭。
@groovy獲取成員變量,會(huì)直接調(diào)get方法,比如下邊user.name會(huì)調(diào)用User的getName方法,我們這里name是Bob,但是我們復(fù)寫了getName,所以getName得到Name: Bob,那如果我們想要的是Bob,怎么辦呢?groovy提供了一種方法,加個(gè)@
直接獲取成員變量的代碼如下
assert user.@name == 'Bob'groovy的函數(shù)定義一般都是用def定義,形參不需要寫明類型,結(jié)束的時(shí)候用return返回,return可省略
def f(a) { a * a;}def f(a, b) { a * b;}assert f(10) == 100assert f(5, 10) == 50如果使用void關(guān)鍵字代替def關(guān)鍵字定義函數(shù),則函數(shù)的返回值將為null函數(shù)不能訪問在外部通過def定義的變量:groovy的類可以不用寫構(gòu)造函數(shù),而在new的時(shí)候指明就可以了。
class Car { String make String model}Car car = new Car(make: 'Peugeot', model: '508')assert car.make == 'Peugeot'http://docs.groovy-lang.org/next/html/documentation/ http://groovy.zeroleaf.com/core-syntax.html http://groovy.zeroleaf.com
新聞熱點(diǎn)
疑難解答