答案是:创建子类对象时不会创建父类对象。
我们创建子类对象时,只是说创建了父类空间,并进行了初始化。如果说创建子类的时候就会创建它的父类,那内存空间中不都是Object类的对象吗?(想想java的设计师也不会这么做的)
作者:祖春雷
这个问题主要涉及到java对象的内存布局。
java对象的内存布局是由对象所属的类确定。也可以这么说,当一个类被加载到虚拟机中时,由这个类创建的对象的布局就已经确定下来的啦。
Hotspot中java对象的内存布局:
每个java对象在内存中都由对象头和对象体组成。
对象头是存放对象的元信息,包括该对象所属类对象Class的引用以及hashcode和monitor的一些信息。
对象体主要存放的是java对象自身的实例域以及从父类继承过来的实例域,并且内部布局满足由下规则:
规则1:任何对象都是8个字节为粒度进行对齐的。
规则2:实例域按照如下优先级进行排列:长整型和双精度类型;整型和浮点型;字符和短整型;字节类型和布尔类型,最后是引用类型。这些实例域都按照各自的单位对齐。
规则3:不同类继承关系中的实例域不能混合排列。首先按照规则2处理父类中的实例域,接着才是子类的实例域。
规则4:当父类中最后一个成员和子类第一个成员的间隔如果不够4个字节的话,就必须扩展到4个字节的基本单位。
规则5:如果子类第一个实例域是一个双精度或者长整型,并且父类并没有用完8个字节,JVM会破坏规则2,按照整形(int),短整型(short),字节型(byte),引用类型(reference)的顺序,向未填满的空间填充。
以上就是java对象的内存布局的规则。
接下来说一下java对象的实例化方法,也就是常见的<init>方法。
当我们new一个对象时,其实jvm已经把这个对象的整个空间已经分配好,并且整个对象的实例域布局已经确定下来啦。
实例化方法<init>就是将对象实例域的值设置到相应空间中。
<init>方法以调用父类的<init>方法开始,以自身构造方法作为结束。实例域的声明与实例初始化语句块的位置关系会影响编译器生成的<init>方法的字节码顺序。
还是以一个例子说明一下:
class Parent {
private short six;
private int age;
}class Sub extend Parent{
private String name;
private int age;
private float price;
}当前Sub对象的内存布局由下:
&lt;img src="https://pic1.zhimg.com/50/v2-4ce1b61927241c3d7eea75248900b552_hd.jpg" data-rawwidth="317" data-rawheight="421" class="content_image" width="317"&gt;
super所谓的父类存储空间的表示到底是什么意思?
这里的super存储我想就是绿色的那个位置吧!
在java继承中,我们说子类继承了父类的所有属性和方法,但是有不能直接使用父类中的private属性和方法。这是不是矛盾呢?
其实这并不矛盾,通过上面的java内存布局我们知道,子类确实继承了父类的所有属性和方法,即拥有了父类的所有的属性和方法,但是拥有不代表可以使用。
比如说:你在银行存了5年的定期存款,这些钱是你所拥有的,但是你现在不能使用它。