比如person是student的父类,在创建对象时
Person p=new student();我们都知道类在虚拟机中的加载机制是
在new对象或引用父类静态成员时开始滴(不完整,情况还有很多),同时会在栈内存中开辟地址给this和super,小弟做过实验,this和super的值一样,都是该对象的地址值,凌乱了那super是怎样指向父类的成员的?
public class Test4 {
public static void main(String[] args) {
Fu z=new Zi();
    }
}
class Fu{
      Fu(){
    System.out.println("Fu");
            }
}
class Zi extends Fu{
        Zi(){
System.out.println(this);
System.out.println(super.toString());
            }
}
加载顺序为先加载父类再加载子类,在加载过程中类的方法也会加载进方法区,包括构造方法。小弟这样理解,因为通过父类引用调用方法时,如果该方法如果被子类重写了调用出来滴就是重写后的方法,那么说明子类的方法在父类加载完后肯定也加载进去了, 那不是方法区中又有父类又有子类的方法,子类中本来就有父类的方法,这样不是很浪费空间? 重写的和没重写的都在里面,我勒个去......
各位技术大神们,一个问题困扰了很久,java中通过父类型引用子类对象时具体过程是怎样的? 小弟泪奔...关于继承的问题内存

解决方案 »

  1.   

    纠结了好半天才弄懂了,加载类当然包括类的成员(成员变量和成员方法,只是存放的区域不一样分别位于堆和方法区中, 因为java对于不同的数据类型的存储方式不同,这也是Java区别其他语言在内存方面的优化),可参考类的加载机制。
    因为所有的类都是Object的子类,所以先加载父类再加载子类不矛盾(Java在这方面很严谨),在加载的过程中会在堆中分配出空间给成员变量就如我一上做过的实验,其实堆中存放了子类以及其(所有)父类的成员,其指向地址值会给栈中的this和super,这也就是为什么this和super值一样的原因,因为指向的对象一样嘛。
    同时在方法区中会先加载父类的方法在加载子类的,子类中其实没有和父类相同的方法,要用怎么办不是有super指向父类吗,子类自己的方法不是有this指向吗,这也就解释了为什么只有在一个类中方法才能相互调用,没有对象怎么调用方法(this帮你做到了)。同时这样也就体现除了继承的特点,加强了代码的复用性和节省了内存的空间。不知道你懂了没,如果不懂自己画下图会加强理解
      

  2.   

    这是对象内部模型问题。
    虽然每个编译器会有自己的具体实现方式,但都会有数据部分和方法部分。
    数据部分有类数据(class data member)和对象数据(object data member)。
    方法部分也一样有类方法(class method)和对象方法(object method)。
    我们可以将这些统称为类成员(class member)和对象成员(object member)。
    类成员(data member or method)是此类的所有实例共享的成员,所以只需要通过类即可访问,比如java里面的静态数据或者方法。
    对象成员(data member or method)是属于类里实例的成员,即因对象而不同,比如java里面的非静态数据或者方法,必须通过对象(类实例)来访问。
    不同的编译器可能有不同的对象模型,但往往是通过指针和表来实现。类数据成员在程序的数据段,所以不需要通过对象来访问;类方法成员在代码段,通过静态地址访问,所以也不需要对象即可访问。对象成员往往是在栈(stack)或者堆(heap)里面动态构建,数据成员很简单,直接分配内存给它们即可。方法则往往通过动态表来实现,所以,如果动态表在调用父类的构造方法之前做好那么构造函数里面调用的方法是多态的,否则不是。比如C++就不是,而Java则是。