在上一次對於groovy環境進行了搭建並寫了一個Helloworld級別的例子感受了一下它的魅力,接下來則來具體學習一下它的語法,要想學得扎實枯燥的語法的坎是必須得過的。
變量:
變量的類型:
- 基本類型:這個跟java差不多,回憶一下:
- 對象類型:也跟Java差不多。
但是!!!在Groovy中基本類型也是對象類型,下面用代碼來論證一下:
基本類型也可以輸出它的class。。看一下結果:
是不是從這個打印中可以得知,在Groovy中都是對象類型,這個需要注意!!
變量的定義:
這塊跟Java就有一些區別了。
- 強類型定義方式:
啥叫強類型定義呢?
也就是在定義變量的時候明確的指定了該變量的類型了,跟我們使用Java風格一樣。
- 強類型def定義方式:
其實在很多其它語言中也有類似的寫法,像Kotlin、Dart之類的,很明顯對於我們聲明的變量完全可以通過等號右側指定的值來推斷出來變量的類型:所以其實沒必要顯示的指定變量的類型,所以groovy就給咱們提供了這種便捷性,使用一個def既可定義任何變量,下面看一下代碼:
那對於這兩種方式實際場景該怎么選擇呢?有以下兩個點要素:
1、這個類只供自己來調用,不會被其它模塊所調用,推薦使用def方式定義變量,這樣我們可以隨時的將其轉換成其它類型。
2、如果說類中的變量是需要用於其它類來調用的,則建議用強類型定義的方式,因為強類型定義的變量是不可能改變類型的,這樣就保證了外界傳給我們的值一定是正確的,而如果這個變量定義成了def,那外界傳遞給你啥類型的值比較合適呢,這樣就不確定了,給調用方造成一個困惑。
下面咱們來修改一下def變量的類型看是否能改類型:
簡單理解:用def定義的弱類型的變量其實是一個Object,可以接收任何類型,而強類型定義的則就是具體的類型。
字符串:
關於Groovy的字符串除了包含Java的字符串外,還有自己的一些字符串,叫GString,下面重點來學習一下:
常用的三種定義方式:
一個單引號:
這個是跟Java不同的地方。
三個單引號:
那。。既然都是表示的String,它們倆有啥區別么,其實是有區別的,這里主要是從字符串格式化的角度來進行看待,對於單引號的字符串如果想要有像換行符之類的出現則只能通過+字符串拼接的方式來達成,而對於三個引號則不需要了,下面來演示一下:
貌似第一行顯示成空行了:
那如果想第一行不輸出空行,而是從這個地方開始輸出呢?
這里需要這樣做:
雙引號:
這個是在Java中字符串的定義方式,在Groovy中當然也支持:
那。。它又有啥特點么?其實它是一種可擴展的字符串,啥叫“可擴展的字符串”呢?其實就是里面可以有變量,看下面:
繼續再來看一個擴展的例子:
那。。難道單引號里面就不能用這種擴展方式么,試一下就知道了:
那,既然在Groovy中字符串一個是String,一個是GString,那它們之間互轉是怎么搞的呢?下面來看一下:
字符串方法:
在Groovy中的String像Java一樣定義了很多的API供使用,其中還有Groovy自己擴展的,下面看一下整個Groovy中String API的分類:
而閉包類型的api放到之后再來學習,所以這里集中來學習一下常見的普通類型的API:
字符串填充API:
center():
當然也可以不指定第二個參數,默認則以空格進行填充了:
padLeft()、padRight():
這個就比較好理解了,直接看例子:
比較方法:
字符串索引:
另外下標還可以傳入下標,如下:
minus():
其中也可以用操作符來實現同步的效果:
reverse():字符串倒序
capitalize():首字母轉大寫
isNumber():判斷是否是數字
轉換成類型:
這塊就不演示了,比較簡單:
邏輯控制:
這塊比較簡單,學一下Groovy跟Java不同的既可:
swich..case..
我們知道在Java中的swich只能是int類型、char類型、String類型、枚舉類型的變量,而在Groovy中就沒這些限制了,可以傳任何類型,下面來看一下:
再來修改一下讓其可以匹配一個數組:
所以在groovy代碼編寫中,如果if..else能用switch..case來代替就盡量用switch..case,因為可讀性比較強。
范圍的for循環:
接下來看一下對於數組的循環,基本類似:
再看一下對於map的循環:
閉包:
基礎:
關於閉包在其它語言中都有,像Kotlin、Dart等,而閉包在Groovy中又是一個非常重要的概念,所以有必要扎實的去掌握它。
閉包概念:
閉包的定義:
首先先來看一下如何定義一個閉包:
閉包的調用:
那對於閉包代碼怎么來執行呢?當然需要有調用才行,如下調用既可:
【糾正】:在上面代碼中提示使用不帶call()的方式來調用閉包是推薦的,其實上面說反了,實際調用建議就是用帶call()的,因為如果不帶call()很容易跟方法的調用混淆,這里做個糾正,下面涉及到的地方我就不一一改了,寫個博客真的太費時間了,這里集中說明一下~~
閉包參數:
普通參數:
在上面也提到了跟方法很類似,我們知道方法都可以有參數,那。。閉包能有么?當然,具體如何寫呢?看下面:
不過上面代碼有個坑,不知能不能看出來:
這里不過多解釋了,改成雙引號完事:
也可以傳一個變量:
那如果有多個參數呢?
隱式參數:
在Groovy中有個語法糖,其實像Kotlin等都有類似的,看一下:
那如果不想要這個默認參數,那你顯示的指定一個參數既可。
閉包返回值:
看一下程序:
這個比較好理解,接下來再來變一下:
基本數據類型與閉包使用:
對於閉包的概念其實比較簡單,但是!!它的使用是非常之靈活的,下面看一下在Groovy中閉包的有如下使用場景:
- 與基本類型的結合使用
- 與String的結合使用
- 與數據結構結合使用【這個在未來學習到數據結構時再來看】
- 與文件等結合使用【這個在未來學習到文件時再來看】
求階乘:
下面先來看一下與基本類型的結合使用,這里來利用閉包的方式來求一個數的階乘:
看一下upto的參數定義:
很明顯求階乘需要有一個循環的,但是我們調用一個API就達到了階乘的效果,很顯然upto里面做工作了,瞅一下它的實現細節:
既然有upto,肯定有downto:
所以,咱們也可以用它來實現同樣的功能:
累加:
其中有一個寫法其實在kotlin中大量運用到:
在Koltin中這樣使用是當參數只有一個Lambda表達式則可以直接用花括號打開,而這個times只接收一個閉包,閉包跟Lambda的意義真的差不多,所以也能這樣寫。下面來瞅一下它的實現:
字符串與閉包結合使用:
接下來再來看一下字符串跟閉包的結合使用,直接看代碼
each的遍歷:
其中看一下each的定義:
其中返回的是self,其實也就是字符串本身,咱們來打印一下返回值:
find:查找符合條件的第一個字符
findAll:找到所有符合條件的字符:
any:根據閉包的條件來返回true或false
看一下它的定義:
every:每一個字符都要滿足條件最終才會返回true
collect:根據閉包的行為最終再產生一個集合
以上是一些常見的用法,都需要在實際練習中去熟悉。
進階:
接下來則要展現一下Groovy的閉包跟其它閉包或Java的Lambda表達式的強大處理,不過也稍加難理解一點,下面走起。
閉包關鍵變量:
Groovy自帶的有如下三個關鍵字:
- this
- owner
- delegate
完全不知道上面有啥用,下面先來在閉包中輸出一下,看都是啥?
居然這三者輸出的對象是一模一樣的呀,那。。學了有啥意義?其實它們是有區別的,具體有啥區別下面繼續來往下探究,先來理解一下這三個關鍵字所代表的含義:
- this:代表閉包定義處的類
- owner:代表閉包定義處的類或對象
從這個文字描述就能感覺到跟this的不同,它還能代表對象,啥意思,因為閉包里面還可以再定義閉包,所以它也對代表當前閉包對象而非只是定義類,關於這個下面會有例子,先了解一下概念。 - delegate:它代表任意對象,默認與owner一致
下面則來定義多個閉包進一步來看它們的區別:
接下來則來調用一下:
也就是說閉包的這三個變量永遠是看最近定義的類,像這個程序很明顯還有一個外部的類:
其實主要是來看一下在里面又定義了一個閉包的輸出,發現輸出還是一樣。。
因為這個閉包中木有定義新的閉包,所以暫時還木有看到this跟owner的區別,在繼續來寫程序之前,這里將static換成實例方法再來看一下輸出:
好,接一下來咱們在閉包中再定義一個閉包,來看一下this和owner的區別:
現在已經知道了this跟onwer的區別了,那。。onwer跟delegate呢?其實默認確實是沒區別,但是!!閉包是可以設置委托的,如果設置了之后則就能知道有啥不一樣了,如下:
閉包委托策略:
那搞清了上面三個閉包的變量有啥用呢?它們就可以用到閉包的委托策略中,如何用,下面直接看代碼:
那有沒有辦法來將name輸出成teacher的呢?當然有,直接修改Student的代碼嘛,但是有沒有一種不通過修改目前的代碼也能達到同樣的效果呢?有!!!使用閉包的委托策略,具體看下面:
這是因為需要設置一下委托策略,如何設置?
那如果Teacher類中木有name變量呢?
而如果我們將委托策略變成這個呢?
從詞面意思是只會從委托對象中來找,很明顯此時找不到,那應該拋異常,試試:
這里看一下總共有幾個委托策略:
其實實際中用到這種委托策略的不多,只有寫框架的可能會用到,做個了解既可。