JavaSE - 多态的本质

JavaSE - 多态的本质

Scroll Down

多态

**场景:**创建一个Animal类,有Dog和Cat类继承Animal类,并重写say( )方法,创建一个Woman类,该类有个Animal类型的成员变量和一个pet( )方法调用对应的say( )方法

package com.sukai.test01;

/**
 * 实现多态
 */
public class Animal {

    public static void main(String[] args) {
        Woman womanA = new Woman(new Cat());
        womanA.Pet();

        Woman womanB = new Woman(new Dog());
        womanB.Pet();

        Woman womanC = new Woman(new Animal());
        womanC.Pet();

    }

    public void say() {
        System.out.println("I am a animal");
    }
}

class Dog extends Animal {

    @Override
    public void say() {
        System.out.println("I am a dog");
    }
}

class Cat extends Animal {
    @Override
    public void say() {
        System.out.println("I am a cat");
    }

}

class Woman {
    private Animal animal;

    Woman(Animal animal) {
        this.animal = animal;
    }

    public void Pet() {
        animal.say();
    }
}

image-20200414160024374

经发现,womanA.Pet();本质上调用的是运行时类的say()方法而不是引用类型的say()

探究多态的本质 - 动态绑定

Human human = new Man();虽然我们new的对象是一个Man()但是它调用的却是Animal()Say()方法

package com.sukai.test01;

public class Human {
    public static void main(String[] args) {
        Human human = new Man();
        human.Say();
    }

    public void Say() {
        System.out.println("I am a human");
    }

}

class Man extends Human {
    @Override
    public void Say() {
        System.out.println("I am a man");
    }
}

内存分析:

如图所示,首先在栈中创建一个变量,它指向Man这个对象,但是由于在调用构造方法时,是把human当成一个Human对象的引用传过来的,所以human只能指向Man对象里面的Human对象,那么现在我们调用human.say(),它就回去代码区中找say( )方法,现在它发现有两个Say( ),那么要调用哪一个呢?此时实际上在父类的内部有一个指向Say( )方法的指针,在程序运行期间,你new的是哪个对象,指针就指向哪个对象的Say( )方法,这就是动态绑定,通过这种动态绑定的方式就可以实现多态了

image-20200414160106733

总结

总结动态绑定(多态):动态绑定是指在“执行期间”(而非编译期间)判断所引用的实际对象类型,根据其实际的类型调用其相应的方法