初始化时的过程
new一个对象时jvm的工作步骤:
1:在栈内存定义变量此时为初始值,定义方法。基本数据类型 int 0 。引用数据类型为null;
2: 调用父类构造方法,定义父类的属性和方法(如果子类已经重写父类的方法 这时不会被覆盖,整个过程不会发生任何覆盖的情况)。
父类的private方法是不能被重写的,你把父类的getNum改成protected 和private结果是不一样的!!
3:给父类的变量赋值。
4:执行父类构造方法中其他语句(此时它自己变量已经初始化和赋值完成,貌似很合理)。
5:给自己变量赋值(在堆内存创建对象或常量)。
6:执行构造方法中其他语句。
初始化的实际过程是:
1、在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制零。
2、调用基类构造器。这个步骤会不断的反复递归下去,首先是构造这种层次结构的根,然后是下一层导出类,等等。直到最低层的导出类。
3、按照声明的顺序调用成员的初始化代码。在类的内部,初始化的顺序是先“静态”,(如果它们尚未因前面的对象创建过程而被初始化),后“非静态”。而非静态变量定义的顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
4、调用导出类的构造器主体。
如果你要在构造器中调用一个方法时,将该方法声明为private。
对于这个规则是需要一些说明的,假使你的父类构造器中要调用一个非静态方法,而这个方法不是private的又被子类所重载,这样在实际创建子类的过程中递归调用到了父类的构造器时,父类构造器对这个方法的调用就会由于多态而实际上调用了子类的方法,当这个子类方法需要用到子类中实例变量的时候,就会由于变量没有初始化而出现异常(至于为什么子类中的实例变量没有初始化可以参考上边的实例初始化过程),这是Java不想看到的情况。而当父类构造器中调用的方法是一个private方法时,多态就不会出现,也就不会出现父类构造器调用子类方法的情况,这样可以保证父类始终调用自己的方法,即使这个方法中调用了父类中的实例变量也不会出现变量未初始化的情况(变量初始化总是在当前类构造器主体执行之前进行)。