Java多态原理(JVM角度)?!

第一次从JVM角度来看Java当中的问题,前期的c语言基础给了我很大帮助。
直接上例子:

class Father{
	int age;
	public Father() {
		age=40;
	}
	void breath() {
		System.out.println("father is breathing..");
	}
}
class Son extends Father{
	int age;
	public Son() {
		age=18;
	}
	void breath() {
		System.out.println("son is breathing..");
	}
	void play() {
		System.out.println("son is playing..");
	}
}

public class Test{
	public static void main(String[] args) {
		Father father=new Son();
		father.breath();
//		father.play()
		System.out.println(father.age);
	}
}

-----output------
son is breathing…
40

可以发现:father.breath()调用的实际上是子类的eat,但father.age调用的还是父类的age,并且father.play()不会通过编译。

解释:
从Father father = new Son()这句话来看,首先会执行new Son(),在堆中分配一个对象,首先要通过JVM的类加载器将Son类对应的class文件加载到JVM中,然后JVM根据class文件中的字节流产生一个表示class文件中类型信息的结构体。
之后,JVM会根据上面这个结构体生成一个方法表。这个方法表是实现java多态关键。
放发表中包含的是实例方法的直接引用,通过这个放发表可以访问到该类的实例方法,而且,这些实例方法不仅包括本类的方法,还包括其父类的实例方法,以及父类的父类的实例方法,一直到顶层Object。(这些方法中不包含私有方法,因为私有方法不能继承)
方法表中的这些直接引用会指向到JVM中表示类型信息的那个结构体的相应的方法上,直接上图:
在这里插入图片描述
我们通过Son的放发表来说,首先方法表中,会产生指向继承自Object类的方法的引用,这些包括指向toString的以及Object中的很多方法,不全部列举。
然后有很关键的一点,方法表中会产生指向继承自Parent类的方法的引用,这里指的是Parent中的breath()方法,图中没有表示,为什么在图中不表示呢?并且代码表示Son类方法表中的breath()方法是他自己的,是因为最后一步是产生指向本类的方法的引用。
当Son类的方法表产生指向Parent类中的方法的引用后,会有一个指向breath方法的引用,最后产生指向本类的方法的引用后,也有一个指向breath的引用,这时,新的数据会覆盖原有的数据,也就是说原来指向Parent.breath()的那个引用会被替换成指向Son.breath()的引用,占据的原来表中的位置。所以我们看到的Son中的breath方法是他自己的。

了解了方法区的结构后,我们来看以下堆中对象的结构:
直接上图:
在这里插入图片描述
接下来看栈区,在那里由于Father father而产生了Father类型的引用,这个引用指向堆区中的Son的实例。
这里的father说白了就是一个地址,这个地址指向堆中的Son的实例,最关键的是修饰father的Father。
让我们到c的语法中,当定义char *p时,由于char只能保存一个字节,所以p只能一个字节一个字节的访问内存,当用int *p时,由于int类型可以保存4个字节,所以p就可以四个字节四个字节的访问内存。
我们简单的看(实际复杂,这里简化的说),Parent实例对象的大小占了两行,而Son实例对象占了三行。
虽然father指向的是Son实例的对象,但是由于Father的修饰,它只能访问两行的数据,也就是说father根本访问不到Son中的age!!!只能访问到Parent中的age。

同样的想法拿到放发表中:
上图:
在这里插入图片描述
我们看到Parent的方法表占了三行,Son占了4行,father虽然指向了Son的实例对象,而对象中也有指针指向Son的方法表,但是由于Father的修饰,通过father只能访问到Child放发表的前两行内容,所以play编译失败。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值