【Java教程】详解Java 多态性
整理:Java面试那些事儿
Java 中的多态性是一个概念,我们可以通过它以不同的方式执行单个操作。多态性源自两个希腊词:poly 和 morphs。“poly”这个词意味着许多,“morphs”意味着形式。所以多态性意味着多种形式。
Java 中有两种类型的多态:编译时多态和运行时多态。我们可以通过方法重载和方法重写来实现java中的多态性。
如果在Java中重载一个静态方法,就是编译期多态的例子。在这里,我们将重点关注 java 中的运行时多态性。
Java 中的运行时多态性
运行时多态性或动态方法调度是一个过程,其中对覆盖方法的调用在运行时而不是编译时解析。
在这个过程中,通过父类的引用变量调用一个被重写的方法。关注公众号鸭哥聊Java。调用方法的确定是根据引用变量引用的对象。
向上转型
如果 Parent 类的引用变量引用 Child 类的对象,则称为向上转型。例如:
class A{}
class B extends A{}
A a=new B();//向上转型
对于向上转型,我们可以使用类类型或接口类型的引用变量。例如:
interface I{}
class A{}
class B extends A implements I{}
在这里,B类的关系是:
B IS-A A
B IS-A I
B IS-A Object
由于Object是Java中所有类的根类,所以我们可以写成B IS-A Object。
Java 运行时多态性示例
由于方法调用是由 JVM 而不是编译器决定的,因此称为运行时多态性。
class Bike{
void run(){System.out.println("行驶");}
}
class Splendor extends Bike{
void run(){System.out.println("安全行驶60km");}
public static void main(String args[]){
Bike b = new Splendor(); //向上转型
b.run();
}
}
输出:
安全行驶60公里
Java 运行时多态性示例:银行
考虑这样一个场景,其中 Bank 是一个提供获取利率的方法的类。但是,利率可能因银行而异。例如,SBI、ICICI 和 AXIS 银行提供 8.4%、7.3% 和 9.7% 的利率。
注意:此示例也在方法覆盖中给出,但没有向上转型。
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 利率:"+b.getRateOfInterest());
b=new ICICI();
System.out.println("ICICI 利率:"+b.getRateOfInterest());
b=new AXIS();
System.out.println("AXIS 利率:"+b.getRateOfInterest());
}
}
输出:
SBI 利率:8.4
ICICI 利率:7.3
AXIS 利率:9.7
Java 运行时多态性示例:Shape
class Shape{
void draw(){System.out.println("绘制...");}
}
class Rectangle extends Shape{
void draw(){System.out.println("绘制矩形...");}
}
class Circle extends Shape{
void draw(){System.out.println("绘制圆形...");}
}
class Triangle extends Shape{
void draw(){System.out.println("绘制三角形...");}
}
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();
}
}
输出:
绘制矩形...
绘制圆形...
绘制三角形...
Java 运行时多态性示例:Animal
class Animal{
void eat(){System.out.println("正在吃...");}
}
class Dog extends Animal{
void eat(){System.out.println("正在吃面包...");}
}
class Cat extends Animal{
void eat(){System.out.println("正在吃老鼠...");}
}
class Lion extends Animal{
void eat(){System.out.println("正在吃肉...");}
}
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();
}}
输出:
正在吃面包...
正在吃老鼠...
正在吃肉...
具有数据成员的 Java 运行时多态性
覆盖的是方法,而不是数据成员,因此数据成员无法实现运行时多态性。
在下面给出的例子中,两个类都有一个数据成员速度限制。我们通过引用子类对象的父类的引用变量访问数据成员。由于我们正在访问未被覆盖的数据成员,因此它将始终访问父类的数据成员。
规则:数据成员不能实现运行时多态性。
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
}
输出:
90
具有多级继承的 Java 运行时多态性
让我们看一下具有多级继承的运行时多态性的简单示例。
class Animal{
void eat(){System.out.println("正在吃");}
}
class Dog extends Animal{
void eat(){System.out.println("吃水果");}
}
class BabyDog extends Dog{
void eat(){System.out.println("喝牛奶");}
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();
}
}
输出:
吃
吃水果
喝牛奶
尝试输出
class Animal{
void eat(){System.out.println("动物正在吃东西...");}
}
class Dog extends Animal{
void eat(){System.out.println("狗正在吃东西...");}
}
class BabyDog1 extends Dog{
public static void main(String args[]){
Animal a=new BabyDog1();
a.eat();
}}
输出:
狗正在吃东西
因为,BabyDog 没有覆盖 eat() 方法,所以调用了 Dog 类的 eat() 方法。
技术交流群
扫码进群记得备注:城市、昵称和技术方向。
往期精选