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