教妹學(xué) Java 第 24 講:instanceof 操作符
嗨,《教妹學(xué) Java》專欄的同學(xué)們,大家好呀,久違了!
連更 23 講后,感覺(jué)實(shí)在是太累了!幾乎每天都在寫(xiě)文章,再加上工作和生活,完全是一副喪尸的模樣,扛不住。于是就不得不停下來(lái)腳步,結(jié)果這一停,直接停到黃花菜都涼了,很多喜歡這個(gè)專欄的同學(xué)在后臺(tái)不停地催啊催!
催催催,于是第 24 講——instanceof 操作符就來(lái)了!這說(shuō)明催催還是有效果的哈。
“哥,我終于該上場(chǎng)了呀!”三妹調(diào)皮的說(shuō),“這段時(shí)間,我可急壞了!”
“我的親妹妹呀,作為補(bǔ)償,五一我?guī)闳埣医缤?,怎么樣?到時(shí)候再給哥拍點(diǎn)帥照作為封面,還有你的,主要是作為同學(xué)們的福利~”我瞥了一眼旁邊的三妹,一聽(tīng)到我要帶她出去玩,臉上立馬是一副期待的樣子。
“那哥,你趕緊開(kāi)始吧,我要學(xué)起來(lái)了!”
instanceof 操作符的用法其實(shí)很簡(jiǎn)單:
(object) instanceof (type)
用意也非常簡(jiǎn)單,判斷對(duì)象是否符合指定的類型,結(jié)果要么是 true,要么是 false。在反序列化的時(shí)候,instanceof 操作符還是蠻常用的,因?yàn)檫@時(shí)候我們不太確定對(duì)象屬不屬于指定的類型,如果不進(jìn)行判斷的話,就容易拋出 ClassCastException 異常。
我們來(lái)建這樣一個(gè)簡(jiǎn)單的類 Round:
class Round {
}
然后新增一個(gè)擴(kuò)展類 Ring:
class Ring extends Round {
}
這時(shí)候,我們就可以通過(guò) instanceof 來(lái)檢查 Ring 對(duì)象是否屬于 Round 類型。
Ring ring = new Ring();
System.out.println(ring instanceof Round);
結(jié)果會(huì)輸出 true,因?yàn)?Ring 繼承了 Round,也就意味著 Ring 和 Round 符合 is-a 的關(guān)系,而 instanceof 操作符正是基于類與類之間的繼承關(guān)系,以及類與接口之間的實(shí)現(xiàn)關(guān)系的。
我們?cè)賮?lái)新建一個(gè)接口 Shape:
interface Shape {
}
然后新建 Circle 類實(shí)現(xiàn) Shape 接口并繼承 Round 類:
class Circle extends Round implements Shape {
}
如果對(duì)象是由該類創(chuàng)建的,那么 instanceof 的結(jié)果肯定為 true。
Circle circle = new Circle();
System.out.println(circle instanceof Circle);
這個(gè)肯定沒(méi)毛病,instanceof 就是干這個(gè)活的,大家也很好理解。那如果類型是父類呢?
System.out.println(circle instanceof Round);
結(jié)果肯定還是 true,因?yàn)橐廊环?is-a 的關(guān)系。那如果類型為接口呢?
System.out.println(circle instanceof Shape);
結(jié)果仍然為 true, 因?yàn)橐卜?is-a 的關(guān)系。如果要比較的對(duì)象和要比較的類型之間沒(méi)有關(guān)系,當(dāng)然是不能使用 instanceof 進(jìn)行比較的。
為了驗(yàn)證這一點(diǎn),我們來(lái)創(chuàng)建一個(gè)實(shí)現(xiàn)了 Shape 但與 Circle 無(wú)關(guān)的 Triangle 類:
class Triangle implements Shape {
}
這時(shí)候,再使用 instanceof 進(jìn)行比較的話,編譯器就報(bào)錯(cuò)了。
System.out.println(circle instanceof Triangle);
錯(cuò)誤信息如下所示:
Inconvertible types; cannot cast 'com.itwanger.twentyfour.instanceof1.Circle' to 'com.itwanger.twentyfour.instanceof1.Triangle'
意思就是類型不匹配,不能轉(zhuǎn)換,我們使用 instanceof 比較的目的,也就是希望如果結(jié)果為 true 的時(shí)候能進(jìn)行類型轉(zhuǎn)換。但顯然 Circle 不能轉(zhuǎn)為 Triangle。
編譯器已經(jīng)提前幫我們預(yù)知了,很聰明。
Java 是一門(mén)面向?qū)ο蟮木幊陶Z(yǔ)言,也就意味著除了基本數(shù)據(jù)類型,所有的類都會(huì)隱式繼承 Object 類。所以下面的結(jié)果肯定也會(huì)輸出 true。
Thread thread = new Thread();
System.out.println(thread instanceof Object);
“那如果對(duì)象為 null 呢?”三妹這時(shí)候插話了。
“這個(gè)還真的是一個(gè)好問(wèn)題啊?!蔽胰滩蛔?duì)三妹豎了一個(gè)大拇指。
System.out.println(null instanceof Object);
只有對(duì)象才會(huì)有 null 值,所以編譯器是不會(huì)報(bào)錯(cuò)的,只不過(guò),對(duì)于 null 來(lái)說(shuō),instanceof 的結(jié)果為 false。因?yàn)樗械膶?duì)象都可以為 null,所以也不好確定 null 到底屬于哪一個(gè)類。
通常,我們是這樣使用 instanceof 操作符的。
// 先判斷類型
if (obj instanceof String) {
// 然后強(qiáng)制轉(zhuǎn)換
String s = (String) obj;
// 然后才能使用
}
先用 instanceof 進(jìn)行類型判斷,然后再把 obj 強(qiáng)制轉(zhuǎn)換成我們期望的類型再進(jìn)行使用。
JDK 16 的時(shí)候,instanceof 模式匹配轉(zhuǎn)了正,意味著使用 instanceof 的時(shí)候更便捷了。
if (obj instanceof String s) {
// 如果類型匹配 直接使用 s
}
可以直接在 if 條件判斷類型的時(shí)候添加一個(gè)變量,就不需要再?gòu)?qiáng)轉(zhuǎn)和聲明新的變量了。
“哇,這樣就簡(jiǎn)潔了呀!”三妹不僅驚嘆到!
好了,關(guān)于 instanceof 操作符我們就先講到這吧,難是一點(diǎn)都不難,希望各位同學(xué)也能夠很好的掌握。
至于下一篇什么時(shí)候會(huì)寫(xiě),大家多催催就是了。這周打算把對(duì)應(yīng)的 GitHub 和碼云,以及 docsify 都重新更新一波~敬請(qǐng)期待。
