java轉(zhuǎn)型(向上與向下)

開始的時候,總是不理解,為什么Java中要有轉(zhuǎn)型這一概念。但是隨著面向?qū)ο笏枷氲募由?,以及對Java的理解深入。才知道,轉(zhuǎn)型真的是Java的特色,更是好東西啊。

話不多說,直接舉例。

首先,我們有兩個類:父類:動物類,子類:人

public class Animal {

public void eat(){

System.out.println("animal eatting...");

}

}

class Human extends Animal{

public void eat(){

System.out.println("human eatting...");

}

public void study(){

System.out.println("human study...");

}

}

class Main{

public static void main(String[] args) {

Animal b=new Human(); //向上轉(zhuǎn)型

b.eat();

b.study();? //此處提示在Animal中沒有定義study方法。

在函數(shù)中,將對象Human向上轉(zhuǎn)型為父類Animal對象,調(diào)用父類的eat方法。這樣看起來沒有什么,但是,實際上在我們實際編程中節(jié)約了很大的代碼量。想象一下,如果沒有向上轉(zhuǎn)型的情況。(粘貼一下別人的代碼,轉(zhuǎn)自六易金鱗http://blog.csdn.net/shanghui815/article/details/6088588)

來看下面的顯示器類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)在有一個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ù)

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)了程序的簡潔性。

回到我們的Animal上面來。為什么,調(diào)用study()方法會出錯呢?因為向上轉(zhuǎn)型父類指向子類引用對象會遺失除與父類對象共有的其他方法,也就是在轉(zhuǎn)型過程中,子類的新有的方法都會遺失掉,在編譯時,系統(tǒng)會提供找不到方法的錯誤。但是如果子類重寫了父類的方法就根據(jù)這個引用指向調(diào)用子類重寫的這個方法(這個方法就是覆蓋override)。這個調(diào)用過程就稱為“動態(tài)綁定”。

好了,再來說一下向下轉(zhuǎn)型:

主要分為兩種情況:

情況一:如果父類引用的對象如果引用的是指向的子類對象,那么在向下轉(zhuǎn)型的過程中是安全的。也就是編譯是不會出錯誤的。

情況二:如果父類引用的對象是父類本身,那么在向下轉(zhuǎn)型的過程中是不安全的,編譯不會出錯,但是運(yùn)行時會出現(xiàn)java.lang.ClassCastException錯誤。它可以使用instanceof來避免出錯此類錯誤。

還是用Animal的例子:

public class Animal {

public void eat(){

System.out.println("animal eatting...");

}

}

class Human extends Animal{

public void eat(){

System.out.println("human eatting...");

}

public void study(){

System.out.println("human study...");

}

}

class Main{

public static void main(String[] args) {

Animal b=new Human(); //向上轉(zhuǎn)型

b.eat();

Human h = (Human)b;//向下轉(zhuǎn)型,編譯和運(yùn)行皆不會出錯

h.eat();

h.study();

Animal b=new Animal();

b.eat();

//Human h2 = (Human)b2;//不安全的向下轉(zhuǎn)型,編譯無錯但會運(yùn)行會出錯

//h2.eat();

//h2.study();

//以此這種向下轉(zhuǎn)型應(yīng)該這樣寫

if(b2 instanceof Human){

Human h2 = (Human)b2;

h2.eat();

h2.study();


總結(jié):

1、父類引用可以指向子類對象,子類引用不能指向父類對象。

2、把子類對象直接賦給父類引用叫upcasting向上轉(zhuǎn)型,向上轉(zhuǎn)型不用強(qiáng)制轉(zhuǎn)型。就像例子:Animal animal = new Human();

3、把指向子類對象的父類引用賦給子類引用叫向下轉(zhuǎn)型(downcasting),要強(qiáng)制轉(zhuǎn)型。

如Animal就是一個指向子類對象的父類引用,把Animal賦給子類引用human 即Human human =(Human)animal;其中animal前面的(Human)必須添加,進(jìn)行強(qiáng)制轉(zhuǎn)換。

4、向上轉(zhuǎn)型(upcasting) 會丟失子類特有的方法,但是子類覆蓋(overriding) 父類的方法,子類方法有效

5、向上轉(zhuǎn)型的作用,減少重復(fù)代碼,父類為參數(shù),調(diào)有時用子類作為參數(shù),就是利用了向上轉(zhuǎn)型。這樣使代碼變得簡潔。體現(xiàn)了JAVA的抽象編程思想。



每天進(jìn)步一點點

推薦微信公眾號【排骨肉段】,記錄日常的美好。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容