JAVA new子类的时候是否会创建父类
问题:
- 学习java基础的记得自己死记硬背这句话:
- 子类创建的时候,会先隐式调用父类无参数构造方法(如果父类没有构造方法,系统则会给父类默认添加无参构造)
- 自己测试过,如果父类有参构造,没有无参构造,子类必须显示调用父类有参构造(如果不调用会报错)
- 结论:子类必须调用父类的构造方法
- 问题: 调用父类构造方法==new 父类?
理论分析
- 从类的加载过程来说:
- 通过类全定名加载这个类class文件(或者满足class文件规范的二进制流)
- 验证
- 准备
- 解析(这个过程是一个递归过程,会递归加载父类class文件,和字段,接口,递归是从 第一步到第四部)
- 初始化(真真new对象)
- 使用
- 销毁
- 分析上面步骤
- 1-4部 是一个递归加载class文件,生成对应Class对象(intanceKlass)
- 初始化这部到底会不会new 父类呢?
- 个人想法: 应该不会,就算会,也只会new一份父类对象,让子类共同使用,因为父类公共项,在只有无参构造的时候的值基本不会变动的,也就是可以理解成一个常量,为什么要重复创建,浪费性能,
- 自己得出来的结论:
- 不会创建的可能性很大(每个对象,都要分配对象头,实例参数,补位,浪费很多空间)
- 就算创建,也应该在复用的基础上面
- 假设不创建: 至少解决 对象头的空间
大胆猜想,拿实践求证
- 上代码:
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);
}
}
- 运行结果:
- 分析结果:
父类里面的构造方法 this 和子类构造方法 this 引用指向的对象都是相同的 - 结论:
子类构造的时候一定会调用父类构造器,初始化公共属性的值
调用构造器!= 会构造父类对象
通过HSDB验证
- HSDB 使用教程:地址
- 注意:需要把 sawindbg.dll 文件复制到 jre/bin jkd/bin两个目录下,要不会报错
- 代码:
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);
}
}
- 查询结果:
- 总结:通过HSDB证明我上面推论,父类会被加载,但是不会被初始化,子类会持有父类的公共属性
附带问题
- 为什么 构造方法,可以用this,this还有指向的地址呢?
- 分析:
- 初始化一个对象的时候,肯定是先开辟一个物理空间,开辟好后,把物理空间地址,返回给this,这个时候,在通过this对物理空间具体值进行修改
- 开辟 ->赋值,所以,在赋值前,对象已经真是存在 在内存里面了,只是对象的值,还没初始化