欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java對象類型轉(zhuǎn)換和多態(tài)性(實例講解)

 更新時間:2017年10月30日 08:41:22   作者:java部落  
下面小編就為大家?guī)硪黄猨ava對象類型轉(zhuǎn)換和多態(tài)性(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

對象類型轉(zhuǎn)換

分為向上轉(zhuǎn)型和向下轉(zhuǎn)型(強(qiáng)制對象轉(zhuǎn)型)。 向上轉(zhuǎn)型是子對象向父對象轉(zhuǎn)型的過程,例如貓類轉(zhuǎn)換為動物類;向下轉(zhuǎn)型是強(qiáng)制轉(zhuǎn)型實現(xiàn)的,是父對象強(qiáng)制轉(zhuǎn)換為子對象。 這和基礎(chǔ)數(shù)據(jù)類型的轉(zhuǎn)換是類似的,byte在需要時會自動轉(zhuǎn)換為int(向上轉(zhuǎn)型),int可以強(qiáng)制轉(zhuǎn)型為byte(向下轉(zhuǎn)型)。

對于對象轉(zhuǎn)型來說, 向上轉(zhuǎn)型后子對象獨有的成員將不可訪問 。 意思是,在需要一只動物時,可以把貓當(dāng)作一只動物傳遞,因為貓繼承自動物,貓具有動物的所有屬性。但向上轉(zhuǎn)型后,貓不再是貓,而是被當(dāng)作動物看待,它自己獨有的屬性和方法就不可見了。換句話說,向上轉(zhuǎn)型后,只能識別父對象中的內(nèi)容。

可以通過"引用變量 instanceof 類名"的方式來判斷引用變量 所指向的對象 是否屬于某個類,也就是說"對象是不是某類",例如聲明一個貓類對象的引用"Cat c",然后"c instanceof Animal"表述的意思是"對象c是一種動物嗎?"對于instanceof返回true的對象,都可以轉(zhuǎn)換為類對象,只不過有些可能需要強(qiáng)制轉(zhuǎn)換。

向上轉(zhuǎn)型可以自動進(jìn)行,這本就是符合邏輯的,狗類繼承自動物類,它本身就是一只動物,因此在需要動物類的時候,丟一只狗過去就會自動向上轉(zhuǎn)型成動物類。但這時狗已經(jīng)不是狗,而是動物,所以狗獨有的成員不再可見。

強(qiáng)制轉(zhuǎn)換的方式和基礎(chǔ)數(shù)據(jù)類型強(qiáng)制轉(zhuǎn)換一樣,都是在待轉(zhuǎn)換對象前加上目標(biāo)類型,例如將動物a強(qiáng)制轉(zhuǎn)換為狗d: Dog d = (Dog)a 。

下面是一個對象類型轉(zhuǎn)換的示例,很好地分析了能否轉(zhuǎn)型、轉(zhuǎn)型后能否訪問某些成員等等。

class Animal {
 String name;
 Animal(String name) {this.name = name;}
}

class Cat extends Animal {
 String eyecolor;
 Cat(String name,String color) {super(name); this.eyecolor = color;}
}

class Dog extends Animal {
 String furcolor;
 Dog(String name,String color) {super(name); this.furcolor = color;}
}

public class OCast {
 public static void main(String [] args) {
 Animal a = new Animal("animal");
 Cat c = new Cat("cat","blue");
 Dog d = new Dog("dog","black");

 System.out.println( a instanceof Animal);//return true
 System.out.println( c instanceof Animal);//return true
 System.out.println( d instanceof Animal);//return true
 System.out.println( a instanceof Cat); //return false

 System.out.println(a.name); //return animal
 a = new Dog("yellowdog","yellow"); //object Dog upcast to Animal
 System.out.println(a.name);  //return yellowdog
 System.out.println(a instanceof Animal); //return true
 System.out.println(a instanceof Dog); //return true
 //System.out.println(a.furcolor); //error! because a was regarded as Animal
 Dog d1 = (Dog)a; // because "a instanceof Dog" is true,so force cast Animal a to Dog
 System.out.println(d1.furcolor);  //return yellow
 }
}

對于上面的 a = new Dog("yellowdog",yellow) ,a是Animal類型,但此時 它指向的是Dog對象。也就是說它是Dog,所以也是Animal類 ,所以 a instanceof Animal); 和 a instanceof Dog; 都是true,這是它的"指針"決定的。 但因為它的類型是Animal類型,類型決定了能存儲什么樣的數(shù)據(jù),對于已經(jīng)存在的但不符合類型的數(shù)據(jù)都是不可見的,所以Animal類型決定了它只能看到Dog對象中的Animal部分 。

如下圖:

既然可以向上轉(zhuǎn)型,配合instanceof的邏輯判斷,就能實現(xiàn)很好的擴(kuò)展性。例如,動物類的sing(Animal a)方法需要的是一個動物類,可以給它一只狗d,這時會向上轉(zhuǎn)型(就像需要double類型卻給了一個int數(shù)據(jù)一樣),雖然轉(zhuǎn)型了,但狗d的實際引用仍然是Dog對象,于是 if (a instanceof Dog) 判斷為真,則調(diào)用能體現(xiàn)狗sing()方法特殊性的語句。如果傳遞一只貓,if判斷一下并調(diào)用能體現(xiàn)貓sing()方法特殊性的語句。這樣,任何時候想添加一只動物,都只需要增加一條if語句就可以了。

見下面的示例:

class Animal {
 String name;
 Animal(String name) {
 this.name = name;
 }
}

class Cat extends Animal {Cat(String name) {super(name);}}
class Dog extends Animal {Dog(String name) {super(name);}}

public class TestCast {
 public static void main(String [] args) {
 TestCast t = new TestCast(); 
 Animal a = new Animal("animal");
 Animal c = new Cat("cat");
 Animal d = new Dog("dog");
 t.sing(a);t.sing(c);t.sing(d);
 }

 void sing(Animal a) {
 if ( a instanceof Cat) {
  Cat cat = (Cat)a;
  System.out.println("cat is singing");
 } else if(a instanceof Dog) {
  Dog dog = (Dog)a;
  System.out.println("dog is singing");
 } else {
  System.out.println("not an instance of animal");
 }
 }
}

如果沒有對象轉(zhuǎn)型,那么Dog里要定義一次sing(),Cat里也要定義一次sing()。要增加一個動物類,動物類里也還要定義一次sing()?,F(xiàn)在就方便多了,直接在sing()方法內(nèi)部修改if語句就可以了。

注意,上面的sing()方法不屬于Animal或其他子類的方法,而是獨立定義在其他類里進(jìn)行調(diào)用的。

多態(tài)

向上轉(zhuǎn)型雖然在一定程度上提高了可擴(kuò)展性,但提高的程度并不太高。以向上轉(zhuǎn)型為基礎(chǔ),java的多態(tài)實現(xiàn)的擴(kuò)展性更好更方便。

多態(tài)也叫動態(tài)綁定或后期綁定,它是執(zhí)行期間進(jìn)行的綁定,而非編譯期間的綁定(這是靜態(tài)綁定或稱為前期綁定)。

多態(tài)的原理是:當(dāng)向上轉(zhuǎn)型后,調(diào)用一個被重寫的方法時,本該調(diào)用的是父類方法,但實際上卻會動態(tài)地調(diào)用子類重寫后的方法。實際上,編譯期間綁定的確實是父類方法,只不過在執(zhí)行期間動態(tài)轉(zhuǎn)調(diào)子類對應(yīng)方法。

例如,Animal類的sing()方法,Cat和Dog類都重寫了sing()方法。當(dāng)需要一個Animal對象時,傳遞了一個Cat類,那么將調(diào)用Cat的sing()方法。動態(tài)綁定的邏輯正如下面的代碼類似:

void sing(Animal a) {
 if ( a instanceof Cat) {
 Cat cat = (Cat)a;
 System.out.println("cat is singing");
 } else if(a instanceof Dog) {
 Dog dog = (Dog)a;
 System.out.println("dog is singing");
 } else {
 System.out.println("not an instance of animal");
 }
}

以下是一個多態(tài)的例子

class Animal {
 private String name;
 Animal(String name) {this.name = name;}

 public void sing(){System.out.println("animal sing...");}
}

class Cat extends Animal {
 private String eyeColor;
 Cat(String n,String c) {super(n); eyeColor = c;}

 public void sing() {System.out.println("cat sing...");}
}

class Dog extends Animal {
 private String furColor;
 Dog(String n,String c) {super(n); furColor = c;}

 public void sing() {System.out.println("dog sing...");}
}

class Lady {
 private String name;
 private Animal pet;
 Lady(String name,Animal pet) {this.name = name; this.pet = pet;}
 public void myPetSing(){pet.sing();}
}

public class DuoTai {
 public static void main(String args[]){
 Cat c = new Cat("catname","blue");
 Dog d = new Dog("dogname","black");
 Lady l1 = new Lady("l1",c);
 Lady l2 = new Lady("l2",d);
 l1.myPetSing();
 l2.myPetSing();
 }
}

編譯后的執(zhí)行結(jié)果為:

cat sing...
dog sing...

在上面的示例中,Lady類的構(gòu)造方法和她調(diào)用sing()方法的代碼為:

Lady(String name,Animal pet) {this.name = name; this.pet = pet;}
public void myPetSing(){pet.sing();}

如果構(gòu)造出Lady對象的pet是Cat對象c,這個c首先會向上轉(zhuǎn)型為Animal類,也就是說Lady的pet屬性雖然指向的是"Cat c"對象,但它只能看見其中的父對象Animal部分。那么 myPetSing(pet.sing();) 方法自然會調(diào)用Animal類的sing()方法。 以上過程是編譯器所認(rèn)為的過程,也是靜態(tài)綁定或前期綁定的過程。

但編譯完成后,雖然pet屬性只能看見Animal部分,但實際在執(zhí)行時pet.sing()卻換轉(zhuǎn)換為執(zhí)行c.sing()。就相當(dāng)于做了一次對象類型強(qiáng)制轉(zhuǎn)換 Cat petx = (Cat)pet 。 這是動態(tài)綁定或后期綁定的過程,也稱為多態(tài)。

實際上,對象在被new出來后,它所涉及到的方法都放在code segment內(nèi)存區(qū)中的一個方法列表中,這個列表中包含了子類、父類的方法,只不過有些時候不可見的方法無法去調(diào)用。當(dāng)執(zhí)行程序時,內(nèi)部的機(jī)制可以從方法列表中搜索出最符合環(huán)境的方法并執(zhí)行它。

實現(xiàn)多態(tài)的技術(shù)的關(guān)鍵點在于:

(1). 定義一個父類引用f,并將其指向子類對象,即進(jìn)行向上轉(zhuǎn)型 ;

(2). 重寫父類的方法,并使用父類引用f去引用這個方法。這樣就可以面向父類進(jìn)行編程 。

正如上面的示例中,將pet定義為Animal類而非具體的子類,并在方法中調(diào)用pet.sing()。如此依賴,就無需考慮pet到底是Cat/Dog,在進(jìn)行功能擴(kuò)展添加Bird類時,完全不用再修改Lady類的這段代碼。

再例如,父類Animal,子類Dog,方法sing()。

class Animal {public void sing(A);}
class Dog extends Animal {public void sing(B);}

public class Test {
 Animal a = new Dog(); //父類引用變量a指向子對象Dog,此時將向上轉(zhuǎn)型
 a.sing();  //使用父類引用變量a引用被重寫的方法sing(),執(zhí)行時將動態(tài)綁定到Dog的sing()
}

以上這篇java對象類型轉(zhuǎn)換和多態(tài)性(實例講解)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入分析Java異常

    深入分析Java異常

    本篇文章給大家詳細(xì)分享了關(guān)于Java異常的相關(guān)知識點,對此有需要的朋友跟著學(xué)習(xí)下吧。
    2018-05-05
  • Java/Android 實現(xiàn)簡單的HTTP服務(wù)器

    Java/Android 實現(xiàn)簡單的HTTP服務(wù)器

    這篇文章主要介紹了Java/Android 如何實現(xiàn)簡單的HTTP服務(wù)器,幫助大家更好的進(jìn)行功能測試,感興趣的朋友可以了解下
    2020-10-10
  • mybatis?查詢方式與效率高低對比

    mybatis?查詢方式與效率高低對比

    這篇文章主要介紹了mybatis?查詢方式與效率高低對比,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Lombok中@EqualsAndHashCode注解的使用及說明

    Lombok中@EqualsAndHashCode注解的使用及說明

    這篇文章主要介紹了Lombok中@EqualsAndHashCode注解的使用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java實現(xiàn)貪吃蛇大作戰(zhàn)小游戲(附源碼)

    Java實現(xiàn)貪吃蛇大作戰(zhàn)小游戲(附源碼)

    今天給大家?guī)淼氖切№椖渴?nbsp;基于Java+Swing+IO流實現(xiàn) 的貪吃蛇大作戰(zhàn)小游戲。實現(xiàn)了界面可視化、基本的吃食物功能、死亡功能、移動功能、積分功能,并額外實現(xiàn)了主動加速和鼓勵機(jī)制,需要的可以參考一下
    2022-07-07
  • SpringBoot中@ComponentScan的使用詳解

    SpringBoot中@ComponentScan的使用詳解

    這篇文章主要介紹了SpringBoot中@ComponentScan的使用詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • spring?boot集成loback日志配置的示例代碼

    spring?boot集成loback日志配置的示例代碼

    這篇文章主要介紹了spring?boot集成loback日志配置的示例代碼,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • Java中對象的深復(fù)制(深克隆)和淺復(fù)制(淺克?。┙榻B

    Java中對象的深復(fù)制(深克?。┖蜏\復(fù)制(淺克?。┙榻B

    這篇文章主要介紹了Java中對象的深復(fù)制(深克?。┖蜏\復(fù)制(淺克?。?,需要的朋友可以參考下
    2015-03-03
  • 詳解spring中的Aware接口功能

    詳解spring中的Aware接口功能

    Spring的依賴注入的最大亮點是所有的Bean對Spring容器的存在是沒有意識的,我們可以將Spring容器換成其他的容器,Spring容器中的Bean的耦合度因此也是極低的,本文重點給大家介紹spring中的Aware接口,感興趣的朋友一起看看吧
    2022-02-02
  • 普通對象使用spring容器中的對象的實現(xiàn)方法

    普通對象使用spring容器中的對象的實現(xiàn)方法

    這篇文章主要介紹了普通對象使用spring容器中的對象的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評論