java实例化顺序

1.继承没有的情况
单独一个类的场景下,初始化顺序为依次为静态数据,继承的基类的构造函数,成员变量,被调用的构造函数。
其中静态数据只会初始化一次。(静态数据包括静态代码块和静态变量,每个类的静态数据只会初始化一次

继承的情况
添加两个基类,让继承父亲,父亲继承祖父。
继承的情况就比较复杂了。由继承了基类,还将往上回溯,递归地调用基类的无参构造方法。
在我们的例子中,在初始化静态数据后,会先往上追溯,调用父的默认构造方法,此时再往上追溯到爷爷的默认构造方法。
注:如果在子类的构造方法中,显式地调用了父类的带参构造方法,那么JVM将调用指定的构造方法而非默认构造方法

分析:

在运行子类(因为主要方法)时JVM首先会装载亚类中,(其中的步骤省略。)

之后会初始化子类类的初始值(程序员在程序中赋予的值)
所有静态变量的初始化都会被JAVA编译器放在一个特殊的方法中称之为类初始化方法,只能被JVM调用。
此时会判断是否存在直接超类,如果还未被初始化,直接初始化超类的静态变量包括块(主动初始化)
所以子类的超类父的静态变量p_StaticField和块首先被初始化,(注意如果声明是最终的就不会初始化它),如果父还有超类的话在此前就应该先初始化父的静态变量,显然对象类没有静态变量和块。
然后初始化子类的静态变量s_StaticField静态状语从句:块
静态变量初始化完成后开始初始化成员变量(new Parent()new为主动初始化)和块
因为静态变量和块在类装载的时候初始化的,具体的实例无关,所以下面的new SubClass(); 只能初始化自身类的成员变量和块,却不能初始化超类的静态变量和块,当然初始化顺序永远是超类先被初始化

总之

总结:对象的初始化顺序:首先执行父类静态的内容(假如静态内容里new了一个静态变量,那么先执行静态变量的构造函数和静态代码块和非静态代码块,如果静态变量的类型就是这个类的本身,就只执行构造函数和非静态代码块,下面会给个例子),父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法。总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法 


例子:

public class Temp{

  private static Temp t=new Temp();

  {
      System.out.println("非静态代码块");
  }
   
  static{
      System.out.println("静态代码块");
  }

  public Temp(){
      System.out.println("构造函数");
  }


   public static void main(String[] args){
       Temp test=new Temp();
   }
}

结果是:

java实例化顺序_第1张图片

这里也可以看出,不管怎么新,一个类的静态内容只会执行一次。


你可能感兴趣的:(java,java,实例化顺序)