new一个对象的时候JVM都做了那些事情
——之前没有进行类加载
*1.类加载,同时初始化类中静态的属性(赋默认值,随即赋声明的值),
* 2.执行静态代码块
3. 为类分配内存空间,初始化非静态的属性 (赋默认值)
4.调用父类构造器
5.父类构造器执行完后,如果自己声明属性的同时有显示的赋值,那么进行显示赋值把默认值覆盖
6.执行匿名代码块
7.执行构造器
8.返回内存地址
——之前已经进行了类加载
1.分配内存空间,同时初始化非静态的属性(赋默认值)
2.调用父类构造器
3.父类构造器执行完后,如果自己声明属性的同时有显示的赋值,那么进行显示赋值把默认值覆盖
4.执行匿名代码块
5.执行构造器
6.返回内存地址
例子:
publicclass Test {
public static void main(String[] args) {
A a = newB();
}
}
classA{
protected String name = "lisi";
public A() {
System.out.println("父类构造器A");
System.out.println("父类构造器A中调用test方法开始,由于子类重写过test方法所以这里执行子类的test方法");
test();
System.out.println("父类构造器A中调用test方法结束");
}
public void test(){
}
}
classB extends A{
private String name = "tom";
{
System.out.println("子类匿名代码块中:"+name);
}
public B() {
System.out.println("子类构造器B");
}
public void test(){
System.out.println("test方法中:this.name="+this.name);
System.out.println("test方法中:super.name="+super.name);
}
}
打印结果:
父类构造器A //子类构造器调用父类构造器
父类构造器A中调用test方法开始,由于子类重写过test方法所以这里执行子类的test方法
test方法中:this.name=null //这个时候父类构造器还没有执行完所以子类中的属性不会显示赋值 所以只有初始的默认值null
test方法中:super.name=lisi //这个时候父类构造器开始调用了 所以父类中的属性已经有了显示赋的值了
父类构造器A中调用test方法结束
子类匿名代码块中:tom //这个时候父类构造器已经调用结束所以子类中的属性已经有了显示赋的值了
子类构造器B
结论: 子类中的属性的显示赋值的时机 是在 父类构造器执行完之后和子类的匿名代码块执行之前的某个时候