java 多态 内存分析_多态机制原理解析--从内存角度分析(转载)

回头看多态,又有了新的认识。

理解多态主要搞清楚以下几个问题就可以了:(以父类Pet,子类Dog为例)

1.为什么可以用表达式 Pet p1= new Dog(); //为什么可以用父类的引用指向子类创建的对象?

2. 当用父类的引用p1,操作子类的对象的时候,为什么可以操作复写(override)的Method,怎么知道该Method是子类的而不是父类的?

3. 当用父类的引用p1操作子类的时候,有哪些限制?

下面进行解答:

理解多态的前提是理解继承(面向对象的三个基本特征:封装、继承、多态)

继承在此不做多的解释,只需要知道两点:1.父类中private 方法或者属性是不能够被继承到子类中;2. 子类实际又两部分组成,一部分是从父类那里copy过来的,还有一部分是自己的。从内存的角度来说,子类在初始化的时候,先初始化继承的那部分,也就是父类的东西(这里的初始化本质可以理解为复制,后面会通过实例进行详细解读),再初始化自己特有的部分。

例如下图,父类Pet中有属性a、还有三种不同类型的sayX方法。子类Dog继承了父类的属性a、public say()以及Protected say1(),还有自己的方法cute。

下面说一下多态机制的原理执行Pet p1=new Dog(); p1虽然是Pet类型的引用,但实际仍然指向Dog,只是操作范围只有从父类继承来的哪些属性或者方法。比如,本例中,p1实际操作范围,只有a,say,say1。不能操作say2,因为say2并没有继承到Dog类中。另外,子类在初始化的时候,也会将父类的方法申明所使用的偏移量赋值一份。

JVM在执行class文件的时候,也就是在内存中执行Java的程序的时候,会将父类的Method,放到Method Table 里面,子类复写了父类中的方法后,初始化子类的时候,就会将Method Table中相应的Method进行覆盖。

另一方面,所有派生类中继承于基类的方法在方法表中的偏移量跟该方法在基类方法表中的偏移量保持一致这也就是为什么可以准确的调用Method。

结合以上两点:p1.say() 之所以能够动态绑定实现多态,本质是Method Table进行了维护。之所以可以写成这样,Pet p1=new Dog() 是因为继承,is-a关系:子类是一种父类。

下面看demo:

class Pet {

int a = 0;

public void say() {

System.out.println("Pet say");

}

protected void say2() {

System.out.println("Pet say2");

}

private void say3() {

System.out.println("Pet say3");

}

}

class Dog extends Pet

{

public void cute(){ System.out.println("Dog cute"); }

public void say(){ System.out.println("Dog say"); }

}

class Cat extends Pet

{

public void cute(){ System.out.println("Cat cute"); }

public void say(){ System.out.println("Cat say"); }

}

public class Zoo {

public static void main(String[] args)

{

Pet p1 = new Dog();

p1.say(); //首先解析一次,得到偏移量,调用方法

p1.say2();//p1 可以调用Protected,不可以调用private类型

Pet p0= new Pet();

p0.a=2;//先初始化了子类,后修改父类的属性,通过打印,

//可以知道,继承后的子类初始化本质是复制,即从父类拷贝了一份“类型+初始值”,然后父类数值上怎么变,和子类无关。

System.out.println("p0.a=="+p0.a);

System.out.println("p1.a=="+p1.a);

Pet p3=new Cat();

p3.say();

打印结果:

Dog say

Pet say2

p0.a==2

p1.a==0

Cat say

笔者就博主的分析对java多态得以如下总结:

多态是在继承的基础之上,父类声明的引用只能调用子类继承到的父类的实例变量和实例方法,对于子类重写了父类方法,则调用子类重写后方法 。总而言之,通过多态获得的还是父类变量和方法,只不过,能够使用的只是子类对父类的继承到的内容和子类重写后的内容!

ps:博主对java多态的认识非常到位,总结的言简意赅。适合javaSE初学者对多态深入理解的参考资料!笔者看完感受颇多,So,收藏于知乎,供各位小伙伴们参考!勿喷哦,哈哈哈哈~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值