6.向上轉(zhuǎn)型

我們在現(xiàn)實(shí)中常常這樣說:這個(gè)人會唱歌蚂且。在這里,我們并不關(guān)心這個(gè)人是黑人還是白人章姓,是成人還是小孩识埋,也就是說我們更傾向于使用抽象概念“人”窒舟。再例如诵盼,麻雀是鳥類的一種(鳥類的子類),而鳥類則是動(dòng)物中的一種(動(dòng)物的子類)洁墙。我們現(xiàn)實(shí)中也經(jīng)常這樣說:麻雀是鳥戒财。這兩種說法實(shí)際上就是所謂的向上轉(zhuǎn)型,通俗地說就是子類轉(zhuǎn)型成父類孝扛。這也符合Java提倡的面向抽象編程思想贫途。來看下面的代碼:

package a.b;

public class A {

public void a1() {

System.out.println("Superclass");

}

}

A的子類B:

package a.b;

public class B extends A {

public void a1() {

System.out.println("Childrenclass"); //覆蓋父類方法

}

public void b1(){} //B類定義了自己的新方法

}

C類:

package a.b;

public class C {

public static void main(String[] args) {

A a = new B(); //向上轉(zhuǎn)型

a.a1();

}

}

如果運(yùn)行C,輸出的是Superclass還是Childrenclass?不是你原來預(yù)期的Superclass咨油,而是Childrenclass柒爵。這是因?yàn)閍實(shí)際上指向的是一個(gè)子類對象餐弱。當(dāng)然囱晴,你不用擔(dān)心瓢谢,Java虛擬機(jī)會自動(dòng)準(zhǔn)確地識別出究竟該調(diào)用哪個(gè)具體的方法氓扛。不過,由于向上轉(zhuǎn)型千所,a對象會遺失和父類不同的方法蒜埋,例如b1()。有人可能會提出疑問:這不是多此一舉嗎待错?我們完全可以這樣寫:

B a = new B();

a.a1();

確實(shí)如此烈评!但這樣就喪失了面向抽象的編程特色讲冠,降低了可擴(kuò)展性。其實(shí)忆家,不僅僅如此德迹,向上轉(zhuǎn)型還可以減輕編程工作量。來看下面的顯示器類Monitor:

package a.b;

public class Monitor{

public void displayText() {}

public void displayGraphics() {}

}

液晶顯示器類LCDMonitor是Monitor的子類:

package a.b;

public class LCDMonitor extends Monitor {

public void displayText() {

System.out.println("LCD display text");

}

public void displayGraphics() {

System.out.println("LCD display graphics");

}

}

陰極射線管顯示器類CRTMonitor自然也是Monitor的子類:

package a.b;

public class CRTMonitor extends Monitor {

public void displayText() {

System.out.println("CRT display text");

}

public void displayGraphics() {

System.out.println("CRT display graphics");

}

}

等離子顯示器PlasmaMonitor也是Monitor的子類:

package a.b;

public class PlasmaMonitor extends Monitor {

public void displayText() {

System.out.println("Plasma display text");

}

public void displayGraphics() {

System.out.println("Plasma display graphics");

}

}

現(xiàn)在有一個(gè)MyMonitor類。假設(shè)沒有向上轉(zhuǎn)型筷转,MyMonitor類代碼如下:

package a.b;

public class MyMonitor {

public static void main(String[] args) {

run(new LCDMonitor());

run(new CRTMonitor());

run(new PlasmaMonitor());

}

public static void run(LCDMonitor monitor) {

monitor.displayText();

monitor.displayGraphics();

}

public static void run(CRTMonitor monitor) {

monitor.displayText();

monitor.displayGraphics();

}

public static void run(PlasmaMonitor monitor) {

monitor.displayText();

monitor.displayGraphics();

}

}

可能你已經(jīng)意識到上述代碼有很多重復(fù)代碼呜舒,而且也不易維護(hù)笨奠。有了向上轉(zhuǎn)型唤殴,代碼可以更為簡潔:

package a.b;

public class MyMonitor {

public static void main(String[] args) {

run(new LCDMonitor()); ??????????????????? //向上轉(zhuǎn)型

run(new CRTMonitor());???????????????????? //向上轉(zhuǎn)型

run(new PlasmaMonitor());??????????? //向上轉(zhuǎn)型

}

public static void run(Monitor monitor) { //父類實(shí)例作為參數(shù)

monitor.displayText();

monitor.displayGraphics();

}

}

我們也可以采用接口的方式朵逝,例如:

package a.b;

public interface Monitor {

abstract void displayText();

abstract void displayGraphics();

}

將液晶顯示器類LCDMonitor稍作修改:

package a.b;

public class LCDMonitor implements Monitor {

public void displayText() {

System.out.println("LCD display text");

}

public void displayGraphics() {

System.out.println("LCD display graphics");

}

}

CRTMonitor乡范、PlasmaMonitor類的修改方法與LCDMonitor類似晋辆,而MyMonitor可以不不作任何修改。

可以看出芋膘,向上轉(zhuǎn)型體現(xiàn)了類的多態(tài)性涩哟,增強(qiáng)了程序的簡潔性贴彼。

5.13.2向下轉(zhuǎn)型

子類轉(zhuǎn)型成父類是向上轉(zhuǎn)型埃儿,反過來說童番,父類轉(zhuǎn)型成子類就是向下轉(zhuǎn)型。但是轨香,向下轉(zhuǎn)型可能會帶來一些問題:我們可以說麻雀是鳥幼东,但不能說鳥就是麻雀根蟹。來看下面的例子:

A類:

package a.b;

public class A {

void aMthod() {

System.out.println("A method");

}

}

A的子類B:

package a.b;

public class B extends A {

void bMethod1() {

System.out.println("B method 1");

}

void bMethod2() {

System.out.println("B method 2");

}

}

C類:

package a.b;

public class C {

public static void main(String[] args) {

A a1 = new B(); //向上轉(zhuǎn)型

a1.aMthod();??? //調(diào)用父類aMthod(),a1遺失B類方法bMethod1()球散、bMethod2()

B b1 = (B) a1; //向下轉(zhuǎn)型蕉堰,編譯無錯(cuò)誤,運(yùn)行時(shí)無錯(cuò)誤

b1.aMthod(); ?? //調(diào)用父類A方法

b1.bMethod1(); //調(diào)用B類方法

b1.bMethod2(); //調(diào)用B類方法

A a2 = new A();

B b2 = (B) a2; //向下轉(zhuǎn)型泻蚊,編譯無錯(cuò)誤丑婿,運(yùn)行時(shí)將出錯(cuò)

b2.aMthod();

b2.bMethod1();

b2.bMethod2();

}

}

從上面的代碼我們可以得出這樣一個(gè)結(jié)論:向下轉(zhuǎn)型需要使用強(qiáng)制轉(zhuǎn)換羹奉。運(yùn)行C程序诀拭,控制臺將輸出:

Exception in thread "main" java.lang.ClassCastException: a.b.A cannot be cast to a.b.B at

a.b.C.main(C.java:14)

A method

A method

B method 1

B method 2

其實(shí)黑體部分的向下轉(zhuǎn)型代碼后的注釋已經(jīng)提示你將發(fā)生運(yùn)行時(shí)錯(cuò)誤。為什么前一句向下轉(zhuǎn)型代碼可以细卧,而后一句代碼卻出錯(cuò)贪庙?這是因?yàn)閍1指向一個(gè)子類B的對象翰苫,所以子類B的實(shí)例對象b1當(dāng)然也可以指向a1奏窑。而a2是一個(gè)父類對象,子類對象b2不能指向父類對象a2撩匕。那么如何避免在執(zhí)行向下轉(zhuǎn)型時(shí)發(fā)生運(yùn)行時(shí)ClassCastException異常墨叛?使用5.7.7節(jié)學(xué)過的instanceof就可以了巍实。我們修改一下C類的代碼:

A a2 = new A();

if (a2 instanceof B) {

B b2 = (B) a2;

b2.aMthod();

b2.bMethod1();

b2.bMethod2();

}

這樣處理后,就不用擔(dān)心類型轉(zhuǎn)換時(shí)發(fā)生ClassCastException異常了令漂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叠必,一起剝皮案震驚了整個(gè)濱河市纬朝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌判没,老刑警劉巖隅茎,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俏竞,死亡現(xiàn)場離奇詭異堂竟,居然都是意外死亡出嘹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門酣胀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丸升,你說我怎么就攤上這事牺氨『锇迹” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵沼头,是天一觀的道長进倍。 經(jīng)常有香客問我,道長陶因,這世上最難降的妖魔是什么楷扬? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任毅否,我火速辦了婚禮蝇刀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捆探。我一直安慰自己黍图,他們只是感情好奴烙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布切诀。 她就那樣靜靜地躺著幅虑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪褒墨。 梳的紋絲不亂的頭發(fā)上擎宝,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天噩咪,我揣著相機(jī)與錄音,去河邊找鬼拘央。 笑死书在,一個(gè)胖子當(dāng)著我的面吹牛儒旬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挡爵,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼茶鹃,長吁一口氣:“原來是場噩夢啊……” “哼闭翩!你這毒婦竟也來了迄埃?” 一聲冷哼從身側(cè)響起侄非,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤逞怨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后宛渐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眯搭,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鳞仙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年棍好,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了借笙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖低散,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情稽鞭,我是刑警寧澤引镊,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布弟头,位于F島的核電站,受9級特大地震影響琴拧,放射性物質(zhì)發(fā)生泄漏蚓胸。R本人自食惡果不足惜除师,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一汛聚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叹哭,春花似錦痕貌、人聲如沸舵稠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盈滴。三九已至,卻和暖如春宽菜,著一層夾襖步出監(jiān)牢的瞬間竿报,已是汗流浹背烈菌。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工芽世, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荠割。 一個(gè)月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓蔑鹦,卻偏偏與公主長得像箕宙,于是被迫代替她去往敵國和親柬帕。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法盼铁,內(nèi)部類的語法饶火,繼承相關(guān)的語法,異常的語法当辐,線程的語...
    子非魚_t_閱讀 31,599評論 18 399
  • 開始的時(shí)候缘揪,總是不理解义桂,為什么Java中要有轉(zhuǎn)型這一概念。但是隨著面向?qū)ο笏枷氲募由羁兜酰约皩ava的理解深入溉瓶。才...
    樂百事52淑熙閱讀 382評論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理堰酿,服務(wù)發(fā)現(xiàn),斷路器坎藐,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 晚報(bào)消息(記者 馮兵田 朱紅專 通訊員 匡偉才)9月28日顺饮,市交警支隊(duì)召開了黃標(biāo)車治理媒體通氣會凌那。 記者從會上了解...
    ld熊壯壯閱讀 180評論 0 0
  • 我不知道為什么會選擇他帽蝶,我不想以緣分來解釋,因?yàn)槲抑肋@不是緣分佃乘,可能是日久生情驹尼,或者說是潛移默化,因?yàn)樵谖业男睦?..
    李蘇珊閱讀 138評論 0 0