柚子快報(bào)邀請(qǐng)碼778899分享:JAVA--多態(tài)
柚子快報(bào)邀請(qǐng)碼778899分享:JAVA--多態(tài)
目錄
1.多態(tài)
1.1多態(tài)的概念
1.2如何實(shí)現(xiàn)多態(tài)
1.3多態(tài)的格式
1.4多態(tài)中的成員變量
1.5重寫的注意事項(xiàng)
1.6多態(tài)的特點(diǎn)
2.引用類型轉(zhuǎn)換
2.1向上轉(zhuǎn)型
2.1.1直接賦值
?2.1.2方法傳參
2.1.3返回值?
2.2向下轉(zhuǎn)型
?2.2.1向下轉(zhuǎn)型的缺點(diǎn)
2.2.2向下轉(zhuǎn)型的防范
3.結(jié)語(yǔ)
1.多態(tài)
1.1多態(tài)的概念
多態(tài)是什么?
多態(tài)是同一個(gè)行為具有不同的表現(xiàn)形式或形態(tài)的能力
同一個(gè)方法可以根據(jù)發(fā)送對(duì)象的不同而采取不同的行為方式
舉個(gè)例子來說:大家生活中常見的打印機(jī),打印機(jī)分為彩色打印機(jī)和黑白打印機(jī),在彩色打印機(jī)的情況下打出的是彩色,在黑白打印機(jī)的情況下打出的是黑白。
總的來說就是:多態(tài)就是事物的多種形態(tài),一個(gè)對(duì)象在不同條件下所表現(xiàn)的不同形式
1.2如何實(shí)現(xiàn)多態(tài)
多態(tài)存在的條件:
1.在多態(tài)中必須存在有繼承或?qū)崿F(xiàn)關(guān)系的子類和父類
2.子類對(duì)父類的某些方法進(jìn)行重新定義
3.通過父類的引用調(diào)用重寫的方法
1.3多態(tài)的格式
父類類名 變量名 = new 子類名();通過變量名.方法名(),這種格式來調(diào)用在子類中重寫的方法
1.4多態(tài)中的成員變量
多態(tài)中的成員變量:編譯運(yùn)行看左邊,即看的是父類的里面的變量。
來給大家舉個(gè)例子:
這個(gè)是父類:
class Animal{
int age = 15;//父類
}
這個(gè)是子類:
class Dog extends Animal{
int age = 10;//子類
}
這個(gè)是啟動(dòng)項(xiàng):
public class Test {
public static void main(String[] args) {
//父親類型 變量名 = new 子類對(duì)象
Animal animal = new Dog();
System.out.println(animal.age);
}
}
讓我們來運(yùn)行一下,來看看結(jié)果 :
多態(tài)里面的成員方法:編譯看左邊,運(yùn)行看右邊
給大家舉個(gè)例子:
這個(gè)是父類:
class Animal{
void eat(){
System.out.println("吃東西");//父類
}
這個(gè)是子類:
class Dog extends Animal{
@Override
void eat() {
System.out.println("吃狗糧");//子類
}
}
這個(gè)是啟動(dòng)項(xiàng):
public class Test {
public static void main(String[] args) {
//父親類型 變量名 = new 子類對(duì)象
Animal animal = new Dog();
animal.eat();
}
}
?讓我們來看一下運(yùn)行結(jié)果:
?當(dāng)子類方法與父類的方法有相同的名稱、返回類型和參數(shù)列表,此時(shí)會(huì)發(fā)生重寫現(xiàn)象,這時(shí)候會(huì)調(diào)用子類的成員方法來取代父類的實(shí)現(xiàn)。
Tip:這里只是針對(duì)調(diào)用子類和父類方法名相同的成員方法所會(huì)發(fā)生的情況。
有人會(huì)問:當(dāng)重寫的方法很多時(shí),有沒有很快捷的方法幫我生成重寫的代碼?
我的回答:有的!
鼠標(biāo)右鍵找到這個(gè)生成(我這里時(shí)下了漢化模組,英文版是Generate):
??然后點(diǎn)擊重寫方法(英文版是Override Methods):
?就歐克了。
1.5重寫的注意事項(xiàng)
重寫的要求:
1.方法名必須相同 2.參數(shù)列表必須相同(類型,個(gè)數(shù),順序) 3.返回值必須相同,如果想要返回值類型不同,則返回關(guān)系類型必須為父子類關(guān)系
重寫的注意事項(xiàng) :
1.父類被private修飾的方法,不能進(jìn)行重寫 2.父類被static修飾的方法,不能進(jìn)行重寫 3.父類被final修飾的方法,不能進(jìn)行重寫,此時(shí)這個(gè)方法被叫作密封方法 4.構(gòu)造方法不能發(fā)生重寫 5.訪問修飾限定符 private < 默認(rèn)權(quán)限(既什么都不寫)< protected < public
子類的訪問修飾限定符權(quán)限一定要大于等于父類,才能發(fā)生重寫現(xiàn)象
我們把重寫這個(gè)運(yùn)行過程叫做動(dòng)態(tài)綁定 。
1.6多態(tài)的特點(diǎn)
當(dāng)子類和父類存在相同的成員變量時(shí),此時(shí)編譯器會(huì)訪問父類的成員變量當(dāng)子類和父類存在相同的成員方法時(shí),此時(shí)會(huì)發(fā)生重寫現(xiàn)象,此時(shí)編譯器會(huì)訪問子類當(dāng)中的成員方法當(dāng)子類中有的方法,而父類沒有時(shí),此時(shí)則不能訪問子類中獨(dú)有的方法子類和父類存在同名的靜態(tài)的成員函數(shù)時(shí),訪問的是父類的成員函數(shù)以上這些特點(diǎn),均是在多態(tài)的情況下發(fā)生的
那有人會(huì)問:子類特有的方法,難道父類真的沒有辦法訪問嘛?
我的回答是:辦法當(dāng)然是有的。
我們先看下這個(gè)例子:
當(dāng)我們嘗試去調(diào)用子類特有的方法是,編譯器報(bào)錯(cuò)了,這是為啥了?還記得我們前面說的嘛,在調(diào)用成員方法是,編譯看左,運(yùn)行看右?,在編譯過程中,沒有發(fā)現(xiàn)父類中有bark這個(gè)方法,所以編譯系統(tǒng)就報(bào)錯(cuò)了,那如何解決呢?請(qǐng)接著往下看。
2.引用類型轉(zhuǎn)換
2.1向上轉(zhuǎn)型
什么是向上轉(zhuǎn)型?
?向上轉(zhuǎn)型是Java中常用的類型轉(zhuǎn)換方式之一,也稱為自動(dòng)類型轉(zhuǎn)換。這種類型轉(zhuǎn)換發(fā)生在繼承關(guān)系中父子類之間,通常是將子類對(duì)象轉(zhuǎn)換為父類對(duì)象?
這里我們有三種方法可以發(fā)生向上轉(zhuǎn)型:
1.直接賦值 2.方法傳參的方式 3.返回值
那就我來給大家一一來列舉
2.1.1直接賦值
class Animal{
String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name + "正在吃");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void wangWang(){
System.out.println(name+"正在汪汪");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog("小狗",10);//直接賦值
animal.eat();
}
}
就像圖中這樣,直接賦值就好了。
?2.1.2方法傳參
就像圖中這樣。
2.1.3返回值?
如圖所示:
以上就是向上轉(zhuǎn)型的三種方式,從上面三種方式看出:?向上轉(zhuǎn)型無法調(diào)用子類特有的方法!
他只能用來調(diào)用父類自己的方法,除非發(fā)生重寫現(xiàn)象,否則無法調(diào)用。
2.2向下轉(zhuǎn)型
什么是向下轉(zhuǎn)型?
將一個(gè)子類對(duì)象向上轉(zhuǎn)型之后可以當(dāng)成父類對(duì)象使用,如果需要調(diào)用子類特有的方法,則需要將父類對(duì)象在轉(zhuǎn)換為子類對(duì)象即可。這就是向下轉(zhuǎn)型
這里我們來以代碼進(jìn)行說明:
class Animal{
String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name + "正在吃");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void special(){
System.out.println("子類特有的方法");
}
public void wangWang(){
System.out.println(name+"正在汪汪");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog("小狗",10);
Dog dog = (Dog)animal;//這里發(fā)生強(qiáng)制轉(zhuǎn)換,將父類強(qiáng)制轉(zhuǎn)換為子類。
dog.special();
dog.eat();
dog.wangWang();
}
運(yùn)行結(jié)果如圖所示:
這里我們看到,不僅將父類的方法調(diào)用出來,而且還把子類特有的方法一起運(yùn)行出來。這就是向下轉(zhuǎn)型的厲害之處。但再厲害的東西還是有缺點(diǎn)的。接下來我們就講一講
?2.2.1向下轉(zhuǎn)型的缺點(diǎn)
雖然我們可以通過向下轉(zhuǎn)型來調(diào)用子類獨(dú)有的方法,但也會(huì)產(chǎn)生下面問題
當(dāng)我們新增加一個(gè)類Cat時(shí),看看會(huì)發(fā)生什么。
這是子類新增的對(duì)象代碼:
class Cat extends Animal{
public Cat(String name, int age) {
super(name, age);
}
public void special1(){
System.out.println("子類特有的方法1");
}
public void miaoMiao(){
System.out.println(name+"正在喵喵叫");
}
}
當(dāng)我們把啟動(dòng)項(xiàng)的代碼改動(dòng)一下,看看會(huì)發(fā)生什么:
改成如下圖所示:
public class Test {
public static void main(String[] args) {
Animal animal = new Cat("小貓",10);
Dog dog = (Dog)animal;//這里發(fā)生強(qiáng)制轉(zhuǎn)換,將父類強(qiáng)制轉(zhuǎn)換為子類。
dog.special();
dog.eat();
dog.wangWang();
}
?此時(shí)我們運(yùn)行下代碼,發(fā)現(xiàn)報(bào)錯(cuò)了
此時(shí)報(bào)錯(cuò)的原因是ClassCastException,即類型轉(zhuǎn)換異常。那為什么會(huì)發(fā)生這種現(xiàn)象了,請(qǐng)聽我解釋:
在啟動(dòng)項(xiàng)中,向上轉(zhuǎn)型的過程,Aniaml aniaml = new Cat();animal這個(gè)對(duì)象是由子類Cat所構(gòu)造出來的而在向下轉(zhuǎn)型的過程中 ,Dog dog = (Dog)animal?把a(bǔ)nimal這個(gè)對(duì)象轉(zhuǎn)變成Dog類的對(duì)象而Dog類和Cat類都是Animal類的子類但通過上面這些步驟,將子類Cat的對(duì)象cat變成兄弟類的對(duì)象dog,此時(shí)不符合向下轉(zhuǎn)型的定義了,故報(bào)錯(cuò)
那我們?nèi)绾慰梢员苊膺@種情況呢?請(qǐng)跟著我往下看。
2.2.2向下轉(zhuǎn)型的防范
如果我們想要避免上述情況,我們可以用到instanceof,instanceof作用就是檢測(cè)其變量類型是否屬于該數(shù)據(jù)類型或者為它的子類類型,我們直接舉例說明:
public class Test {
public static void main(String[] args) {
Animal animal = new Cat("小貓",10);
if(animal instanceof Cat){
Cat cat = (Cat)animal;
cat.special1();
}
else{
Dog dog = (Dog)animal;
dog.special();
}
?就像圖中這樣,如果引用的是Cat這個(gè)子類對(duì)象,則會(huì)打印出Cat中特有的方法,如果引用的是Dog這個(gè)子類對(duì)象,則會(huì)打印出Dog中特有的方法,運(yùn)行結(jié)果如下:
?完整版代碼:
class Animal{
String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name + "正在吃");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Cat extends Animal{
public Cat(String name, int age) {
super(name, age);
}
public void special1(){
System.out.println("子類特有的方法1");
}
public void miaoMiao(){
System.out.println(name+"正在喵喵叫");
}
}
class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void special(){
System.out.println("子類特有的方法");
}
public void wangWang(){
System.out.println(name+"正在汪汪叫");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Cat("小貓",10);
if(animal instanceof Cat){
Cat cat = (Cat)animal;
cat.special1();
}
else{
Dog dog = (Dog)animal;
dog.special();
}
}
3.結(jié)語(yǔ)
第一次寫這么多的內(nèi)容,如有不好的地方請(qǐng)大家指出。希望大家都會(huì)被自己滿意的offer錄取。
柚子快報(bào)邀請(qǐng)碼778899分享:JAVA--多態(tài)
好文閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。