新聞中心
1. 介紹
本篇內(nèi)容為Groovy學習第32篇,學習Groovy語法中的提升與強制轉(zhuǎn)換相關(guān)知識點。(Promotion和coercion)

在潮安等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供網(wǎng)站制作、成都做網(wǎng)站 網(wǎng)站設(shè)計制作按需制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),高端網(wǎng)站設(shè)計,成都全網(wǎng)營銷,成都外貿(mào)網(wǎng)站制作,潮安網(wǎng)站建設(shè)費用合理。
學習在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ù)值之間的提升,是按照該表格的關(guān)系進行的。
2.2 閉包closure的類型轉(zhuǎn)換
在前面介紹閉包相關(guān)知識的時候,有介紹過閉包中的各種轉(zhuǎn)換,相關(guā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泛型。
interface Predicate{
boolean accept(T obj)
}
具有單個抽象方法的抽象類:
abstract class Zinyan {
abstract String getName()
void hello() {
println "Hello, $name"
}
}
可以使用as運算符將任何閉包轉(zhuǎn)換為SAM類型:
Predicate filter = { it.contains 'G' } as Predicate
assert filter.accept('Groovy') == true
Greeter greeter = { 'Groovy' } as Greeter
greeter.hello() //輸出:Hello, Groovy
從Groovy 2.2.0 開始,as Type表達式是可選的。我們可以省略它,只需編寫:
Predicate filter = { it.contains 'G' }
assert filter.accept('Groovy') == true
Greeter greeter = { 'Groovy' }
greeter.hello() //輸出:Hello, Groovy
PS: 上面的 { it.contains 'G' }就是一個閉包對象哦
這意味著我們也可以使用方法指針,如下例所示:
boolean doFilter(String s) { s.contains('G') }
Predicate filter = this.&doFilter
assert filter.accept('Groovy') == true
Greeter greeter = GroovySystem.&getVersion
greeter.hello() //輸出:Hello, Groovy2.2.2 調(diào)用接受帶有閉包的SAM類型的方法
關(guān)閉SAM類型強制的第二個也是可能更重要的用例是調(diào)用接受SAM類型的方法。設(shè)想以下方法:
publicList filter(List source, Predicate predicate) {
source.findAll { predicate.accept(it) }
}
然后,可以使用閉包調(diào)用它,而無需創(chuàng)建接口的顯式實現(xiàn):
assert filter(['Java','Groovy'], { it.contains 'G'} as Predicate) == ['Groovy']
從Groovy 2.2.0開始,還可以省略顯式強制,并像使用閉包一樣調(diào)用該方法:
assert filter(['Java','Groovy']) { it.contains 'G'} == ['Groovy']
這樣做的優(yōu)點是允許我們在方法調(diào)用中使用閉包語法,也就是說,將閉包放在括號之外,從而提高了代碼的可讀性。
2.2.3 對任意類型的強制閉包
上面介紹了SAM單例對象的強制轉(zhuǎn)換,這里介紹其他的類型。
除了SAM類型之外,閉包還可以強制到任何類型,尤其是特定的接口。讓我們定義以下接口:
interface FooBar {
int foo()
void bar()
}
定義了一個接口對象,它有兩個方法分別是foo和bar。我們可以使用as關(guān)鍵字將閉包強制到接口中:
def impl = { println 'ok'; 123 } as FooBar
這將生成一個類,所有方法都使用閉包實現(xiàn):
assert impl.foo() == 123
impl.bar() //輸出: ok
但也可以強制對任何類進行閉包。例如,我們可以用class替換我們定義的接口,而不改變assert斷言的結(jié)果:
class FooBar {
int foo() { 1 }
void bar() { println 'bar' }
}
def impl = { println 'ok'; 123 } as FooBar
assert impl.foo() == 123
impl.bar()
PS: 斷言結(jié)果不滿足是會出新錯誤并停止程序繼續(xù)執(zhí)行的
2.3 Map強制轉(zhuǎn)換成類型
通常使用一個閉包來實現(xiàn)一個接口或一個具有多個方法的類是不可行的。作為替代方案,Groovy允許將Map?強制到接口或類中。在這種情況下,Map?的鍵被解釋為方法名,而值是方法實現(xiàn)。以下示例說明了將Map強制到迭代器中:
def map
map = [
i: 10,
hasNext: { map.i > 0 },
next: { map.i-- },
]
def iter = map as Iterator
當然,這是一個相當做作的例子,但說明了這個概念。我們只需要實現(xiàn)那些實際調(diào)用的方法,但如果調(diào)用的方法在映射中不存在,則會引發(fā)MissingMethodException或
UnsupportedOperationException,具體取決于傳遞給調(diào)用的參數(shù),如下例所示:
interface X {
void f()
void g(int n)
void h(String s, int n)
}
x = [ f: {println "f called"} ] as X
x.f() // 正常的方法調(diào)用
x.g() // MissingMethodException 異常觸發(fā)
x.g(5) // UnsupportedOperationException 異常觸發(fā)
異常的類型取決于調(diào)用本身:
MissingMethodException:如果調(diào)用的參數(shù)與接口/類中的參數(shù)不匹配,就會觸發(fā)該異常警告。
UnsupportedOperationException:如果調(diào)用的參數(shù)與接口/類的重載方法之一匹配,就會觸發(fā)該異常警告。
2.4 String強制轉(zhuǎn)換成enum
Groovy允許透明String?(或GString)強制枚舉值。假設(shè)定義了以下枚舉:
enum State {
up,
down
}
則可以將字符串分配給枚舉,而不必使用顯式作為強制:
State st = 'up'
assert st == State.up
也可以使用GString作為值:
def val = "up"
State st = "${val}"
assert st == State.up
但是,這會引發(fā)運行時錯誤(IllegalArgumentException):
State st = 'not an enum value'
注意,也可以在switch語句中使用隱式強制:
State switchState(State st) {
switch (st) {
case 'up':
return State.down // 顯式賦值
case 'down':
return 'up' // 返回類型的隱式強制
}
}
特別是,請查看case?如何使用字符串常量。但如果調(diào)用一個使用帶有String?參數(shù)的枚舉的方法,則仍必須使用as作為強制:
assert switchState('up' as State) == State.down
assert switchState(State.down) == State.up
2.5 自定義類型強制轉(zhuǎn)換
類可以通過實現(xiàn)asType?方法來定義自定義強制策略。自定義強制是使用as?運算符調(diào)用的,并且從不隱式。例如,假設(shè)定義了兩個類,Polar和Cartesian,如以下示例所示:
class Polar {
double r
double phi
}
class Cartesian {
double x
double y
}
你想從極坐標轉(zhuǎn)換成笛卡爾坐標。一種方法是在Polar類中定義asType方法:
def asType(Class target) {
if (Cartesian==target) {
return new Cartesian(x: r*cos(phi), y: r*sin(phi))
}
}
這允許使用as強制運算符:
def sigma = 1E-16
def polar = new Polar(r:1.0,phi:PI/2)
def cartesian = polar as Cartesian
assert abs(cartesian.x-sigma) < sigma
把所有這些放在一起,Polar類看起來像這樣:
class Polar {
double r
double phi
def asType(Class target) {
if (Cartesian==target) {
return new Cartesian(x: r*cos(phi), y: r*sin(phi))
}
}
}
但也可以在Polar類之外定義asType,如果想為“封閉”類或不擁有源代碼的類定義自定義強制策略,例如使用元類:
Polar.metaClass.asType = { Class target ->
if (Cartesian==target) {
return new Cartesian(x: r*cos(phi), y: r*sin(phi))
}
}
PS: 自定義類型轉(zhuǎn)換主要的就是關(guān)鍵方法asType了。實現(xiàn)asType方法,然后自己就可以定義各種類型的轉(zhuǎn)換了。
2.6 類文本vs變量和as運算符
只有對類有靜態(tài)引用時,才能使用as關(guān)鍵字,如以下代碼所示:
interface Greeter {
void greet()
}
def greeter = { println 'Hello, Groovy!' } as Greeter // Greeter is known statically
greeter.greet()
但是,如果通過反射獲得類,例如通過調(diào)用class.forName,該怎么辦?
Class clazz = Class.forName('Greeter')
嘗試使用as關(guān)鍵字對類的引用將失?。?/p>
greeter = { println 'Hello, Groovy!' } as clazz
// throws:
// unable to resolve class clazz
// @ line 9, column 40.
// greeter = { println 'Hello, Groovy!' } as clazz
會出現(xiàn)異常錯誤,因為as?關(guān)鍵字只對類文本有效。我們需要調(diào)用asType方法:
greeter = { println 'Hello, Groovy!' }.asType(clazz)
greeter.greet()
3. 小結(jié)
到這里,Groovy中有關(guān)于強制轉(zhuǎn)換和類型提升的相關(guā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)深入學習。
文章題目:Groovy語法Promotion提升和Coercion強制轉(zhuǎn)換學習
網(wǎng)站路徑:http://m.fisionsoft.com.cn/article/cdcohjg.html


咨詢
建站咨詢
