Groovy 語法 Promotion提升和Coercion強(qiáng)制轉(zhuǎn)換學(xué)習(xí)
1. 介紹
本篇內(nèi)容為Groovy學(xué)習(xí)第32篇,學(xué)習(xí)Groovy語法中的提升與強(qiáng)制轉(zhuǎn)換相關(guān)知識(shí)點(diǎn)。(Promotion和coercion)
學(xué)習(xí)在Groovy中的各種數(shù)據(jù)類型的各種強(qiáng)制轉(zhuǎn)換和類型變換。
如果不了解Groovy中的數(shù)據(jù)時(shí)如何進(jìn)行轉(zhuǎn)換的,那么可以學(xué)習(xí)一下本篇內(nèi)容,應(yīng)該能夠給你一些參考。
2. 提升和強(qiáng)制轉(zhuǎn)換
2.1 數(shù)值轉(zhuǎn)換
整數(shù)提升:數(shù)字提升的規(guī)則在數(shù)學(xué)運(yùn)算一節(jié)中有詳細(xì)說明。[4. Groovy語法-Number和Boolean數(shù)據(jù)類型學(xué)習(xí) (zinyan.com)](https://zinyan.com/?p=389#2.5-數(shù)學(xué)運(yùn)算)
主要就是下圖所示的,數(shù)值類型的轉(zhuǎn)換。
byte | char | short | int | long | BigInteger | float | double | BigDecimal | |
byte | int | int | int | int | long | BigInteger | double | double | BigDecimal |
char | int | int | int | long | BigInteger | double | double | BigDecimal | |
short | int | int | long | BigInteger | double | double | BigDecimal | ||
int | int | long | BigInteger | double | double | BigDecimal | |||
long | long | BigInteger | double | double | BigDecimal | ||||
BigInteger | BigInteger | double | double | BigDecimal | |||||
float | double | double | double | ||||||
double | double | double | |||||||
BigDecimal | BigDecimal |
不同數(shù)值之間的提升,是按照該表格的關(guān)系進(jìn)行的。
2.2 閉包c(diǎn)losure的類型轉(zhuǎn)換
在前面介紹閉包相關(guān)知識(shí)的時(shí)候,有介紹過閉包中的各種轉(zhuǎn)換,相關(guān)知識(shí)點(diǎn)可以通過:https://zinyan.com/?p=461,https://zinyan.com/?p=462,https://zinyan.com/?p=463了解。?
這里只是進(jìn)行簡單的復(fù)習(xí)和介紹。
2.2.1 SAM單例對(duì)象,進(jìn)行閉包轉(zhuǎn)換
SAM類型是定義單個(gè)抽象方法的類型。例如我們創(chuàng)建接口:它的入?yún)⑹莻€(gè)T泛型。
具有單個(gè)抽象方法的抽象類:
可以使用as運(yùn)算符將任何閉包轉(zhuǎn)換為SAM類型:
從Groovy 2.2.0 開始,as Type表達(dá)式是可選的。我們可以省略它,只需編寫:
PS: 上面的 { it.contains 'G' }就是一個(gè)閉包對(duì)象哦
這意味著我們也可以使用方法指針,如下例所示:
2.2.2 調(diào)用接受帶有閉包的SAM類型的方法
關(guān)閉SAM類型強(qiáng)制的第二個(gè)也是可能更重要的用例是調(diào)用接受SAM類型的方法。設(shè)想以下方法:
然后,可以使用閉包調(diào)用它,而無需創(chuàng)建接口的顯式實(shí)現(xiàn):
從Groovy 2.2.0開始,還可以省略顯式強(qiáng)制,并像使用閉包一樣調(diào)用該方法:
這樣做的優(yōu)點(diǎn)是允許我們?cè)诜椒ㄕ{(diào)用中使用閉包語法,也就是說,將閉包放在括號(hào)之外,從而提高了代碼的可讀性。
2.2.3 對(duì)任意類型的強(qiáng)制閉包
上面介紹了SAM單例對(duì)象的強(qiáng)制轉(zhuǎn)換,這里介紹其他的類型。
除了SAM類型之外,閉包還可以強(qiáng)制到任何類型,尤其是特定的接口。讓我們定義以下接口:
定義了一個(gè)接口對(duì)象,它有兩個(gè)方法分別是foo和bar。我們可以使用as關(guān)鍵字將閉包強(qiáng)制到接口中:
這將生成一個(gè)類,所有方法都使用閉包實(shí)現(xiàn):
但也可以強(qiáng)制對(duì)任何類進(jìn)行閉包。例如,我們可以用class替換我們定義的接口,而不改變assert斷言的結(jié)果:
PS: 斷言結(jié)果不滿足是會(huì)出新錯(cuò)誤并停止程序繼續(xù)執(zhí)行的
2.3 Map強(qiáng)制轉(zhuǎn)換成類型
通常使用一個(gè)閉包來實(shí)現(xiàn)一個(gè)接口或一個(gè)具有多個(gè)方法的類是不可行的。作為替代方案,Groovy允許將Map?強(qiáng)制到接口或類中。在這種情況下,Map?的鍵被解釋為方法名,而值是方法實(shí)現(xiàn)。以下示例說明了將Map強(qiáng)制到迭代器中:
當(dāng)然,這是一個(gè)相當(dāng)做作的例子,但說明了這個(gè)概念。我們只需要實(shí)現(xiàn)那些實(shí)際調(diào)用的方法,但如果調(diào)用的方法在映射中不存在,則會(huì)引發(fā)MissingMethodException或
UnsupportedOperationException,具體取決于傳遞給調(diào)用的參數(shù),如下例所示:
異常的類型取決于調(diào)用本身:
MissingMethodException:如果調(diào)用的參數(shù)與接口/類中的參數(shù)不匹配,就會(huì)觸發(fā)該異常警告。
UnsupportedOperationException:如果調(diào)用的參數(shù)與接口/類的重載方法之一匹配,就會(huì)觸發(fā)該異常警告。
2.4 String強(qiáng)制轉(zhuǎn)換成enum
Groovy允許透明String?(或GString)強(qiáng)制枚舉值。假設(shè)定義了以下枚舉:
則可以將字符串分配給枚舉,而不必使用顯式作為強(qiáng)制:
也可以使用GString作為值:
但是,這會(huì)引發(fā)運(yùn)行時(shí)錯(cuò)誤(IllegalArgumentException):
注意,也可以在switch語句中使用隱式強(qiáng)制:
特別是,請(qǐng)查看case?如何使用字符串常量。但如果調(diào)用一個(gè)使用帶有String?參數(shù)的枚舉的方法,則仍必須使用as作為強(qiáng)制:
2.5 自定義類型強(qiáng)制轉(zhuǎn)換
類可以通過實(shí)現(xiàn)asType?方法來定義自定義強(qiáng)制策略。自定義強(qiáng)制是使用as?運(yùn)算符調(diào)用的,并且從不隱式。例如,假設(shè)定義了兩個(gè)類,Polar和Cartesian,如以下示例所示:
你想從極坐標(biāo)轉(zhuǎn)換成笛卡爾坐標(biāo)。一種方法是在Polar類中定義asType方法:
這允許使用as強(qiáng)制運(yùn)算符:
把所有這些放在一起,Polar類看起來像這樣:
但也可以在Polar類之外定義asType,如果想為“封閉”類或不擁有源代碼的類定義自定義強(qiáng)制策略,例如使用元類:
PS: 自定義類型轉(zhuǎn)換主要的就是關(guān)鍵方法asType了。實(shí)現(xiàn)asType方法,然后自己就可以定義各種類型的轉(zhuǎn)換了。
2.6 類文本vs變量和as運(yùn)算符
只有對(duì)類有靜態(tài)引用時(shí),才能使用as關(guān)鍵字,如以下代碼所示:
但是,如果通過反射獲得類,例如通過調(diào)用class.forName,該怎么辦?
嘗試使用as關(guān)鍵字對(duì)類的引用將失敗:
會(huì)出現(xiàn)異常錯(cuò)誤,因?yàn)閍s?關(guān)鍵字只對(duì)類文本有效。我們需要調(diào)用asType方法:
3. 小結(jié)
到這里,Groovy中有關(guān)于強(qiáng)制轉(zhuǎn)換和類型提升的相關(guān)知識(shí)就分享完畢了。以上內(nèi)容可以通過Groovy官網(wǎng)文檔:
[Groovy Language Documentation (groovy-lang.org)](http://docs.groovy-lang.org/docs/groovy-4.0.6/html/documentation/#_promotion_and_coercion)深入學(xué)習(xí)。























