查看原文
其他

【Java教程】详解Java 多态性

点击关注👉 鸭哥聊Java 2023-09-01

整理: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 AB IS-A IB IS-A Object


由于Object是Java中所有类的根类,所以我们可以写成B IS-A Object。


领取福利
点击领取:651页Java面试题库


Java 运行时多态性示例


在这个例子中,我们创建了两个类 Bike 和 Splendor。Splendor 类扩展了 Bike 类并覆盖了它的 run() 方法。我们通过父类的引用变量调用 run 方法。由于它引用了子类对象,并且子类方法重写了父类方法,因此在运行时调用子类方法。


由于方法调用是由 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.4ICICI 利率:7.3AXIS 利率: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() 方法。



技术交流群


扫码进群记得备注:城市、昵称和技术方向


 

往期精选


  1. 我司为什么禁止使用阿里巴巴Java规范?

  2. 【Java教程】详解Java final 关键字

  3. 首个封禁GPT的国家是....,OpenAI CEO:我觉得没违规!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存