【java基础】父类与子类中各成员初始化顺序

java中子类与父类的初始化顺序每次遇到都会想一想,尤其是遇到复杂的子类与父类中多态和方法重载交织在一起的时候,但是总结一下,还是那个特定的规律。

看个例子吧。

class Egg{
	static{
		System.out.println("父类静态代码块初始化");
	}
    private int  a = 1;
    {
    	System.out.println("父类代码块初始化" + a + "  b=1证明成员变量已经初始化了");
    }
    
    public Egg(){
        System.out.println("父类构造函数初始化");
    }
}

class BigEgg extends Egg{
	static{
		System.out.println("子类静态代码块初始化");
	}
	private int  b = 2;
    {
    	System.out.println("子类代码块初始化 " + b + "  b=2证明成员变量已经初始化了");
    }
    public BigEgg(){
        System.out.println("子类构造函数初始化");
    }
}

public class TestClassInitSeq{
	 public static void main(String[] args){
	        new BigEgg();
	 }
}
输出结果:

父类静态代码块初始化
子类静态代码块初始化
父类代码块初始化1  b=1证明成员变量已经初始化了
父类构造函数初始化
子类代码块初始化 2  b=2证明成员变量已经初始化了
子类构造函数初始化

从输出结果可以看出这样的初始化顺序:

① 如果类中存在继承关系,则首先会初始化基类(Egg),然后再是子类(BigEgg);

② 在基类中首先会初始化静态的东西,静态代码块和静态变量(类变量),谁在前就先初始化谁,静态的东西是跟着类的加载而加载的;

③ 然后是初始化子类静态的东西,静态代码块和静态变量,跟父类中的顺序相同,还是谁在前先初始化谁;

④ 接着是父类代码块和成员变量,同样也是谁在前谁先初始化;

⑤ 初始化父类的构造函数(调用有参就初始化有参构造器);

⑥ 接着初始化子类的代码块和成员变量,谁在前谁先初始化;

⑦ 初始化子类的构造函数(调用有参就初始化有参构造器)。

举个例子再来说明和验证一下:

class Father0
{	
   private static String str = "静态变量初始化";
   static{
          System.out.println("父类静态代码块初始化" );
          System.out.println(str);
   }
   
   {
          System.out.println("父类代码块初始化" );
   }
   
   private static String s= print();
   public static String print()
   {
          System.out.println("父类静态方法" );
          return "父类静态成员变量的初始化" ;
   }
   public Father0()
   {
          System.out.println("父类无参构造函数初始化完成" );
          show();
   }
   public void show()
   {
          System.out.println("父类show()方法" );
   }
}
class Son extends Father0
{
   static{
          System.out.println("子类静态代码块初始化" );
   }
   {
          System.out.println("子类代码块初始化" );
   }
   private int i =1;
   private String s="子类私有成员变量" ;
   
   public Son()
   {
          System.out.println("子类构造函数初始化完成" );
          System.out.println("子类成员变量初始化完成:s=" +s);
          show();
   }
   public void show()
   {
          System.out.println("子类show()方法:i=" +i);
   }
}
public class TestClassLoadSeq {
    public static void main(String[] args){
           new Son();
   }
}

输出结果:

父类静态代码块初始化
静态变量初始化
父类静态方法
子类静态代码块初始化
父类代码块初始化
父类无参构造函数初始化完成
子类show()方法:i=0
子类代码块初始化
子类构造函数初始化完成
子类成员变量初始化完成:s=子类私有成员变量
子类show()方法:i=1

从输出结果看,顺序完全是按照上面总结的那个顺序。不同的是父类中有了两个静态变量,而且父类中第二个静态变量指向一个静态方法,所以才有了父类静态方法的初始化。

父类构造函数中调用了一个show()方法,由于是new 子类的实例,所以执行的是子类的show()方法,但是子类的成员变量在父类构造函数执行时还没有初始化,所以此时i=0,当子类中构造函数执行时,调用show()方法,此时成员变量已经初始化了输出i=1。

实际上,本文讨论的都是真正执行的顺序,没有站在JVM的类加载的立场,JVM加载类时做了很多初始化动作,会对每个基本数据类型初始化为各个基本数据类型的0,比如int型会初始化为0,boolean型初始化为false,组合引用类型初始化为null等等

反正,这些基础知识对后面学习还是有一定帮助的,不会让你每次遇到时都要犹豫和徘徊一下。

如有错误望指正。





你可能感兴趣的:(Java基础,java,初始化,类中成员初始化)