Java中的多態(tài)是一個(gè)概念,通過(guò)它我們可以通過(guò)不同的方式執(zhí)行單個(gè)動(dòng)作(方法)。 多態(tài)性派生自2個(gè)希臘詞:“poly”和“morphs”。 詞語(yǔ)“poly”意為許多,“morphs”意為形式。 所以多態(tài)表示為多種形式。
在Java中有兩種類(lèi)型的多態(tài)性:編譯時(shí)多態(tài)性和運(yùn)行時(shí)多態(tài)性。 我們可以通過(guò)方法重載和方法覆蓋在java中執(zhí)行多態(tài)性。
如果在Java中重載靜態(tài)方法,它就是編譯時(shí)多態(tài)性的例子。 這里,我們將關(guān)注Java中的運(yùn)行時(shí)多態(tài)性。
運(yùn)行時(shí)多態(tài)性或動(dòng)態(tài)方法分派是一個(gè)過(guò)程,它對(duì)重寫(xiě)方法的調(diào)用在運(yùn)行時(shí)體現(xiàn)而不是編譯時(shí)。
在此過(guò)程中,通過(guò)超類(lèi)的引用變量調(diào)用重寫(xiě)的方法。 要調(diào)用的方法基于引用的對(duì)象。
了解運(yùn)行時(shí)多態(tài)性之前,讓我們先來(lái)向上轉(zhuǎn)換。
向上轉(zhuǎn)換
當(dāng)父類(lèi)的引用變量引用子類(lèi)的對(duì)象時(shí),稱為向上轉(zhuǎn)換。 例如:
class A{}
class B extends A{}
A a=new B(); //向上轉(zhuǎn)換...
Java運(yùn)行時(shí)多態(tài)性示例1
在這個(gè)例子中,我們創(chuàng)建兩個(gè)類(lèi):Bike和Splendar。 Splendar類(lèi)擴(kuò)展Bike類(lèi)并覆蓋其run()方法。通過(guò)父類(lèi)(Bike)的引用變量調(diào)用run方法。 因?yàn)樗米宇?lèi)對(duì)象,并且子類(lèi)方法覆蓋父類(lèi)方法,子類(lèi)方法在運(yùn)行時(shí)被調(diào)用。
因?yàn)榉椒ㄕ{(diào)用是由JVM不是編譯器決定的,所以它被稱為運(yùn)行時(shí)多態(tài)性。
class Bike {
void run() {
System.out.println("running");
}
}
class Splender extends Bike {
void run() {
System.out.println("running safely with 60km");
}
public static void main(String args[]) {
Bike b = new Splender();// upcasting - 向上轉(zhuǎn)換
b.run();
}
}
執(zhí)行上面代碼得到以下結(jié)果 -
running safely with 60km.
Java運(yùn)行時(shí)多態(tài)性示例2:Bank
考慮一種情況,Bank類(lèi)是一個(gè)提供獲得利率的方法的類(lèi)。 但是,利率可能因銀行而異。 例如,SBI,ICICI和AXIS銀行分別提供8.4%,7.3%和9.7%的利率。

注意:此示例也在方法覆蓋中給出,但沒(méi)有向上轉(zhuǎn)換。
class Bank {
float getRateOfInterest() {
return 0;
}
}
class SBI extends Bank {
float getRateOfInterest() {
return 8.4f;
}
}
class ICICI extends Bank {
float getRateOfInterest() {
return 7.3f;
}
}
class AXIS extends Bank {
float getRateOfInterest() {
return 9.7f;
}
}
class TestPolymorphism {
public static void main(String args[]) {
Bank b;
b = new SBI();
System.out.println("SBI Rate of Interest: " + b.getRateOfInterest());
b = new ICICI();
System.out.println("ICICI Rate of Interest: " + b.getRateOfInterest());
b = new AXIS();
System.out.println("AXIS Rate of Interest: " + b.getRateOfInterest());
}
}
上面代碼執(zhí)行結(jié)果如下 -
SBI Rate of Interest: 8.4
ICICI Rate of Interest: 7.3
AXIS Rate of Interest: 9.7
Java運(yùn)行時(shí)多態(tài)性示例3:Shape
class Shape { // 基類(lèi)(形狀)
void draw() {
System.out.println("drawing...");
}
}
class Rectangle extends Shape {
void draw() {
System.out.println("drawing rectangle...");
}
}
class Circle extends Shape {
void draw() {
System.out.println("drawing circle...");
}
}
class Triangle extends Shape {
void draw() {
System.out.println("drawing triangle...");
}
}
class TestPolymorphism2 {
public static void main(String args[]) {
Shape s;
s = new Rectangle();
s.draw();
s = new Circle();
s.draw();
s = new Triangle();
s.draw();
}
}
上面代碼執(zhí)行結(jié)果如下 -
SBI Rate of Interest: 8.4
ICICI Rate of Interest: 7.3
AXIS Rate of Interest: 9.7
Java運(yùn)行時(shí)多態(tài)性示例4:Animal
class Animal {
void eat() {
System.out.println("eating...");
}
}
class Dog extends Animal {
void eat() {
System.out.println("eating bread...");
}
}
class Cat extends Animal {
void eat() {
System.out.println("eating rat...");
}
}
class Lion extends Animal {
void eat() {
System.out.println("eating meat...");
}
}
class TestPolymorphism3 {
public static void main(String[] args) {
Animal a;
a = new Dog();
a.eat();
a = new Cat();
a.eat();
a = new Lion();
a.eat();
}
}
上面代碼執(zhí)行結(jié)果如下 -
eating bread...
eating rat...
eating meat...
上面示例中,都是有關(guān)方法被覆蓋而不是數(shù)據(jù)成員,因此運(yùn)行時(shí)多態(tài)性不能由數(shù)據(jù)成員實(shí)現(xiàn)。
在下面給出的例子中,這兩個(gè)類(lèi)都有一個(gè)數(shù)據(jù)成員:speedlimit,通過(guò)引用子類(lèi)對(duì)象的父類(lèi)的引用變量來(lái)訪問(wèn)數(shù)據(jù)成員。 由于我們?cè)L問(wèn)的數(shù)據(jù)成員沒(méi)有被重寫(xiě),因此它將訪問(wèn)父類(lèi)的數(shù)據(jù)成員。
規(guī)則: 運(yùn)行時(shí)多態(tài)性不能由數(shù)據(jù)成員實(shí)現(xiàn)。
class Bike {
int speedlimit = 90;
}
class Honda3 extends Bike {
int speedlimit = 150;
public static void main(String args[]){
Bike obj=new Honda3();
System.out.println(obj.speedlimit);//90
}
}
上面代碼執(zhí)行結(jié)果如下 -
90
下面讓我們來(lái)看看一個(gè)帶有多級(jí)繼承的運(yùn)行時(shí)多態(tài)性的簡(jiǎn)單例子。
class Animal {
void eat() {
System.out.println("eating");
}
}
class Dog extends Animal {
void eat() {
System.out.println("eating fruits");
}
}
class BabyDog extends Dog {
void eat() {
System.out.println("drinking milk");
}
public static void main(String args[]) {
Animal a1, a2, a3;
a1 = new Animal();
a2 = new Dog();
a3 = new BabyDog();
a1.eat();
a2.eat();
a3.eat();
}
}
上面代碼執(zhí)行結(jié)果如下 -
eating
eating fruits
drinking Milk
嘗試下面一段代碼的輸出:
class Animal {
void eat() {
System.out.println("animal is eating...");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog is eating...");
}
}
class BabyDog1 extends Dog {
public static void main(String args[]) {
Animal a = new BabyDog1();
a.eat();
}
}
執(zhí)行上述代碼,結(jié)果如下:
Dog is eating
因?yàn)椋?code>BabyDog不會(huì)覆蓋eat()方法,所以這里是Dog類(lèi)的eat()方法被調(diào)用。