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