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

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


咨詢
建站咨詢
