Java多态

1 什么是Java多态

Java中的多态是一个概念,通过它我们可以以不同的方式执行单个操作。多态性源自两个希腊词:poly和morphs。单词“poly”表示很多,“morphs”表示形式。因此,多态性意味着多种形式。

Java中有两种类型的多态:编译时多态运行时多态。我们可以通过方法重载和方法覆盖在Java中执行多态。

如果重载Java中的静态方法,则它是编译时多态性。在这里,本章节我们将重点介绍Java中的运行时多态性。

2 Java的运行时多态

运行时多态性是一个在运行时而不是编译时对覆盖方法的调用过程。

在运行时多态中,我们将通过父类的引用变量调用覆盖的方法。

首先让我们了解运行时多态之前的向上转换。

2.1 向上转换

如果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

3 Java运行时多态的示例

在下面示例中,我们将创建两个类Bike和Splendor。Splendor类继承Bike类并覆盖其run() 方法。我们通过Parent类的引用变量来调用run方法。由于它指向了子类对象,并且子类方法覆盖了Parent类方法,因此在运行时将调用子类方法。

由于方法调用是由JVM而不是编译器确定的,因此称为运行时多态。

/**
 * 一点教程网 - http://www.yiidian.com
 */
//运行时多态的示例
class Bike{
    void run(){
        System.out.println("自行车在跑...");
    }
}
class Splendor extends Bike{
    void run(){
        System.out.println("辉煌牌自行车在跑...");
    }

    public static void main(String args[]){
        Bike b = new Splendor();//向上转换,运行时多态
        b.run();
    }
}

输出结果为:

辉煌牌自行车在跑...

4 Java运行时多态示例:Bank

有这个一个场景,其中Bank是提供获取利率的方法的类。但是,利率可能因银行而异。例如,ICBC,CCB和HSBC银行提供的利率分别为8.4%,7.3%和9.7%。

/**
 * 一点教程网 - http://www.yiidian.com
 */
//运行时多态的示例
class Bank{
    float getRateOfInterest(){
        return 0;
    }
}
class ICBC extends Bank{
    float getRateOfInterest(){
        return 8.4f;
    }
}
class CCB extends Bank{
    float getRateOfInterest(){
        return 7.3f;
    }
}
class HSBC extends Bank{
    float getRateOfInterest(){
        return 9.7f;
    }
}
class TestPolymorphism{
    public static void main(String args[]){
        Bank b;
        b=new ICBC();
        System.out.println("ICBC贷款利率是: "+b.getRateOfInterest());
        b=new CCB();
        System.out.println("CCB贷款利率是: "+b.getRateOfInterest());
        b=new HSBC();
        System.out.println("HSBC贷款利率是: "+b.getRateOfInterest());
    }
}

输出结果为:

ICBC贷款利率是: 8.4
CCB贷款利率是: 7.3
HSBC贷款利率是: 9.7

5 Java运行时多态示例:Shape

/**
 * 一点教程网 - http://www.yiidian.com
 */
//运行时多态的示例
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();
    }
}

输出结果为:

绘制长方形...
绘制圆形...
绘制三角形...

6 Java运行时多态示例:Animal

/**
 * 一点教程网 - http://www.yiidian.com
 */
//运行时多态的示例
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();
    }}

输出结果为:

吃面包...
吃老鼠...
吃肉...

7 字段无法实现运行时多态

方法可以被覆盖,但是字段无法被覆盖,因此字段无法实现运行时多态。

在下面给出的示例中,两个类都有一个字段speedlimit。我们通过父类的引用变量访问这个字段,父类引用指向了子类对象。但是我们发现始终访问Parent类的speedlimit字段值。

/**
 * 一点教程网 - http://www.yiidian.com
 */
//字段无法实现运行时多态
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

8 多级继承的Java运行时多态

让我们看一下拥有多级继承的运行时多态的简单示例。

/**
 * 一点教程网 - http://www.yiidian.com
 */
//拥有多级继承的运行时多态
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();
    }
}  

输出结果为:

在吃东西...
吃水果...
喝牛奶...

另一个例子:

/**
 * 一点教程网 - http://www.yiidian.com
 */
//拥有多级继承的运行时多态
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() 方法。

一点教程,一个分享编程知识的公众号。跟着站长一起学习和进步。

通俗易懂,深入浅出,一篇文章只讲一个知识点。

在公交、在地铁、在厕所都可以阅读,随时随地涨姿势。

文章不涉及代码,不烧脑细胞,人人都可以学习。

当你决定关注「一点教程」,你已然超越了90%的程序员!

一点教程二维码