日期:2014-05-20  浏览次数:20773 次

关于继承 多态的内存问题 求解释

class t1{
void run(){
System.out.println("t1跑");
}
}
class t2 extends t1{
void run(){
System.out.println("t2跑");
}
void cry(){
System.out.println("t2哭");
}



根据自己看的一些内容我的简单理解继承。
在内存中比如父类1mb
现在实例化一个子类,我们比如子类中自己的成员变量和方法是0.5mb,子类中为了继承父类的成员变量和方法就必须通过一定的方式来进行,而一般的得到完整的成员变量和方式就是通过实例化,所以这就是为什么子类实例化的时候一定会调用父类的构造方法不管是隐式还是显示的调用,那么也就可以理解为现在子类有1.5mb,其中1mb相当于是实例化的一个父类,其中在用super指针进行指向这1mb。

t1 t=new t2();也就相当于实例化一个子类对象1.5mb,但是要赋值给父类对象,那么这时t就指向这个子类对象的super指针也就是那1mb。
那么这就能解释为什么对象t调用不了t2成员变量和方法cry等。



现在如果把t1的run注释,之后
通过反射可以证实
t1 t=new t2();
Method[] f=t.getClass().getDeclaredMethods();
for(Method ff:f){
System.out.println(ff.getName());
}
确实就是那1mb,不会出来run方法。
以上我是个人理解肯定又不对的希望指出,下面是我的疑问

再来现在不注释掉t1的run进行重写,那么现在t调用run(),却是子类的进行重写后的run,知道这是多态,了解到是关于对象有两张张表等,但具体是怎么来实现的,特别是内存中是怎么玩的?

而且现在这个时候父类的run方法还存在么?还是子类的重写后相当于指针直接对父类该方法进行赋值达到覆盖?


再有现在把父类的run方法写成私有的,继承的时候私有的还是会进行继承通过反射也知道只是不能用罢了,那现在是还是重写么,而且按理说父类和子类都有run方法用对象t调用不管jvm是调用哪一个都应该是可以运行的,但是现在又报错不让执行,为什么?


真心求研究啊!
内存 继承 多态

------解决方案--------------------
我认为t1 t=new t2();和t2 t = new t2();两者所占的内存是一样

都是new了一个t2对象 只是把指针付给的对象不同 但并不会改变内存的占用

举个例子 你和你父亲 

你父亲会的你都会  而且做的更好  但你会的有些事情 你父亲并不会

但你为了模仿你父亲 你不能做一些你父亲不会做的事情   但这些事情本生在你身上还是存在的
------解决方案--------------------
个人觉得  子类里面复写了run之后,就等于覆盖了super的run  用t1 t = new t2()调用runu是调用t2.run()了


改成private的之后,getDeclareM..()
通过反射获取的时候,需要setAccessible(true),对private的属性和方法要使用暴力反射才能取到,而且改成private后,调用的是t1的run().
------解决方案--------------------

java 中的静态绑定和动态绑定,也就是所谓的“前期绑定”和“后期绑定(运行时绑定)”。
  Father f=new Son(); 将父类的引用类型变量指向子类的实例
  
  绑定:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。 
  方法的绑定问题:
静态绑定:在java中只有方法的静态绑定只发在当方法被 static 、final、private所修饰时和方法是构造方法才是前期绑定的。

动态绑定:jvm会先根据引用类型变量被声明的类型,在其方法列表上进行查找,如果要调用的方法是static\final\private,那么编译器就可以确定要调用的就是这个方法,这点是确定的。如果要调用的方法不是静态绑定的方法,那么才会执行时期去找具体实例对象中的方法列表中的对应的方法。

静态绑定成员变量:对于每个类的成员变量来说,只有一种静态绑定的方式。在编译时期就可以确定每个成员变量的调用。类成员变量没有动态绑定。