简体   繁体   English

当我们使用超类引用变量创建子类的对象时,内存如何分配给超类和子类成员

[英]How memory allocates to superclass and subclass members when we create object of subclass using superclass reference variable

class A {
    int y = 10;

    void m1() {
        System.out.println("This is M1");
        int b = 20;
    }
}

public class B extends A {

    int x = 10;
    int y = 20;

    void m1() {
        System.out.println("This is M2");
    }

    public static void main(String[] args) {
        A a = new B();
        System.out.println(a.y);
        a.m1();
    }

}

What will be the memory allocation chart/diagram for this? 内存分配图表/图表将是什么?

  • new B : new B
    • B is allocated, size of B (includes size of A) all field defaulted B已分配,B的大小(包括A的大小)默认为所有字段
    • constructor of B() : B()构造函数:
      • super.A() called; super.A()被调用; recurses: 递归:
        • constructor of A() : A()构造函数:
        • super.Object() called; super.Object()被调用; recurses 递归
        • all initialized fields of A are assigned: A.this.y = 10; 分配了A的所有初始化字段: A.this.y = 10;
        • rest of the A constructor statements is executed 其余的A构造函数语句被执行
      • all initialized fields of B are assigned: B.this.x = 10; B.this.y = 20; B的所有初始化字段都被分配: B.this.x = 10; B.this.y = 20; B.this.x = 10; B.this.y = 20;
      • rest of the B constructor statements is executed 其余的B构造函数语句被执行

So the allocation is primarily done in the new . 因此,分配主要在new完成。

The allocation done in the constructor and field initialisations can be illustrated in the next corner cast (to be avoided): 在构造函数和字段初始化中完成的分配可在下一个强制转换中说明(避免):

class A {
    A() {
        init(); // VERY BAD STYLE
    }
    protected void init() {
    }
}

class B extends A {
    String s1 = null;
    String s2;
    String s3 = "s3";
    String s4;
    String s5 = "s5";
    B() {
        // s1: null, s2: null, s3: null, s4: null, s5: null
        // super() called, calling init()
        // s1: "i1", s2: "i2", s3: "i3", s4: null, s5: null
        // field initialisation:
        // - s1 = null; s3 = "s3"; s5 = "s5";
        // s1: null, s2: "i2", s3: "i3", s4: null, s5: "s5"
        // remaining code of constructor
    }

    @Override
    protected void init() {
        // s1: null, s2: null, s3: null, s4: null, s5: null
        s1 = "i1";
        s2 = "i2";
        s3 = "i3";
        // s1: "i1", s2: "i2", s3: "i3", s4: null, s5: null
    }
}

The above shows the starting life times of fields, and the unexpected moments if someone ever uses overridable methods in a constructor . 上面显示了字段的起始寿命,以及某人曾经在构造函数中使用可重写方法的意外时刻。

It also shows that in the constructor of A the super fields already exist (with default values null, 0, false, 0.0, ... ). 它还显示在A的构造函数中,超级字段已经存在(默认值为null, 0, false, 0.0, ... )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM