JAVA new子类的时候是否会创建父类

问题:

  1. 学习java基础的记得自己死记硬背这句话:
  1. 子类创建的时候,会先隐式调用父类无参数构造方法(如果父类没有构造方法,系统则会给父类默认添加无参构造)
  2. 自己测试过,如果父类有参构造,没有无参构造,子类必须显示调用父类有参构造(如果不调用会报错)
  3. 结论:子类必须调用父类的构造方法
  1. 问题: 调用父类构造方法==new 父类?

理论分析

  1. 从类的加载过程来说:
  1. 通过类全定名加载这个类class文件(或者满足class文件规范的二进制流)
  2. 验证
  3. 准备
  4. 解析(这个过程是一个递归过程,会递归加载父类class文件,和字段,接口,递归是从 第一步到第四部)
  5. 初始化(真真new对象)
  6. 使用
  7. 销毁
  1. 分析上面步骤
  1. 1-4部 是一个递归加载class文件,生成对应Class对象(intanceKlass)
  2. 初始化这部到底会不会new 父类呢?
  1. 个人想法: 应该不会,就算会,也只会new一份父类对象,让子类共同使用,因为父类公共项,在只有无参构造的时候的值基本不会变动的,也就是可以理解成一个常量,为什么要重复创建,浪费性能,
  2. 自己得出来的结论:
  1. 不会创建的可能性很大(每个对象,都要分配对象头,实例参数,补位,浪费很多空间)
  2. 就算创建,也应该在复用的基础上面
  3. 假设不创建: 至少解决 对象头的空间

大胆猜想,拿实践求证

  1. 上代码:
public class A {

    private String a;

    public A(String a){
        this.a=a;
        System.out.println(this);
    }

    public static void main(String[]args){
        B b=new B("b");

    }
}

public class B extends  A {

    private String b;

    public B(String b) {
        super(b+b);
        this.b=b;
        System.out.println(this);
    }
}
  1. 运行结果:
  2. 分析结果:
    父类里面的构造方法 this 和子类构造方法 this 引用指向的对象都是相同的
  3. 结论:
    子类构造的时候一定会调用父类构造器,初始化公共属性的值
    调用构造器!= 会构造父类对象

通过HSDB验证

  1. HSDB 使用教程:地址
  2. 注意:需要把 sawindbg.dll 文件复制到 jre/bin jkd/bin两个目录下,要不会报错
  3. 代码:
public class A {

    private String pri;

    protected  String pro;

    public String pub;


    public A(){
        this.pri="pri";
        this.pro="pro";
        this.pub="pub";
    }
}
public class B extends A {

    private String b;

    public  B(){
        this.b="b";
    }
}
public class Main {
    public static void main(String[] args) {
        A a = new B();
        System.out.println(a);
    }
}
  1. 查询结果:
  2. 总结:通过HSDB证明我上面推论,父类会被加载,但是不会被初始化,子类会持有父类的公共属性

附带问题

  1. 为什么 构造方法,可以用this,this还有指向的地址呢?
  2. 分析:
  1. 初始化一个对象的时候,肯定是先开辟一个物理空间,开辟好后,把物理空间地址,返回给this,这个时候,在通过this对物理空间具体值进行修改
  2. 开辟 ->赋值,所以,在赋值前,对象已经真是存在 在内存里面了,只是对象的值,还没初始化