Java 类加载执行顺序

时间:2022-03-14 14:05:01

Java类加载时,静态初始化块、静态成员变量、非静态初始化块、构造函数,及子类加载过程中父类的加载过程。通过以下代码可以总结:

 class Parent
{
{
System.out.println("父类非静态初始化块");
}

static
{
System.out.println("父类静态初始化块");
}

public static int t = parentStaticMethod2();

public Parent()
{
System.out.println("父类的构造方法");
}

public static int parentStaticMethod()
{
System.out.println("父类的静态方法");
return 10;
}
public static int parentStaticMethod2()
{
System.out.println("父类的静态方法2");
return 9;
}

@Override
protected void finalize() throws Throwable
{
// TODO Auto-generated method stub
super.finalize();
System.out.println("销毁父类");
}

}


class Child extends Parent
{
{
System.out.println("子类非静态初始化块");
}
static
{
System.out.println("子类静态初始化块");
}
public Child()
{
System.out.println("子类的构造方法");
}
public static int childStaticMethod()
{
System.out.println("子类的静态方法");
return 1000;
}
@Override
protected void finalize() throws Throwable
{
// TODO Auto-generated method stub
super.finalize();
System.out.println("销毁子类");
}
}


public class Test
{

public static void main(String[] args)
{
// Parent.parentStaticMethod();
System.out.println("-------------");
Child child = new Child();

}

}

运行main方法中的  Parent.parentStaticMethod(); ,输出结果:

父类静态初始化块
父类的静态方法2
父类的静态方法


注释点 Parent.parentStaticMethod();  运行 new Child();  输出结果:

父类静态初始化块
父类的静态方法2
子类静态初始化块
父类非静态初始化块
父类的构造方法
子类非静态初始化块
子类的构造方法

如果,同时运行这个两行,输出结果:

父类静态初始化块
父类的静态方法2
父类的静态方法
-------------
子类静态初始化块
父类非静态初始化块
父类的构造方法
子类非静态初始化块
子类的构造方法



可以看出, 子类加载过程中的加载顺序:

父类静态初始化块 --> 父类静态成员变量  --> 子类静态初始化块 --> 父类非静态初始化块 -->父类构造方法-->子类非静态初始化块-->子类构造方法。


更多解释参考一网友的博客:http://www.cnblogs.com/awkshare/articles/4196551.html

Java使用构造器来对单个对象进行初始化操作,使用构造器先完成整个Java对象的状态初始化,然后将Java对象返回给程序,从而让该Java对象的信息更加完整。与构造器作用非常类似的是初始化块,它也可以对Java对象进行初始化操作 一个类里可以有多个初始化块,相同类型的初始化块之间有顺序:前面定义的初始化块先执行,后面定义的初始化块执行 [修饰符]  {         //初始化块的可执行性代码         。。。 } 初始化块的修饰符只能是static,使用static修饰的初始化块被称为静态初始化。初始化块里的代码可以包含任何可执行性语句,包括定义局部变量 ,调用其他对象的方法,以及使用分支,循环语句等 下面定义一个初始化块也有构造器   public class Person {     {//定义第一个初始化块         int a= 6;//初始化块中         if (a >4){             System.out.println("Person初始化块:局部变量a的值大于4");          }         System.out.println("Person的初始化块"); }   //定义第二个初始化块 {     System.out.println("Person 的第二个初始化块"); } //定义无参数的构造器 public Person(){     System.out.println("Person类的无参数构造器"); } public static void main(String[] args){     new Person(); } }   初始化块和构造器 从某种程度上来看,初始化块是构造器的补充,初始化块总是在构造器执行之前执行。   初始化块跟构造器不同的是初始化块是一段固定执行的代码,他不能接收任何参数。 通过把多个构造器中的相同代码提取到初始化块中定义,能更好地提高初始化代码的复用,提高整个应用的可维护性 与构造器类似,创建一个Java对象时,不仅会提高该类的图片初始化块和构造器,而且系统会一直上朔到Java.lang.Object类,先执行该类的初始化块,开始执行该类的构造器,一次向下执行器父类的初始化块,开始执行其父类的构造器,最后才执行该类的初始化块和构造器,返回该类的不对象   静态初始化块 如果定义初始化块时使用了static修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块。静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行。因此静态初始化块总是比普通初始化块先执行。   静态初始化块是类相关的,用于对整个类进行初始化处理,通常用于对类Field执行初始化处理,静态初始化块不能对实例Field进行初始化处理 静态初始化块也被称为类初始化块,也属于类的静态成员,同样需要遵循静态成呢个有不能访问非静态成员的规则,因此静态初始化块不能访问非静态成员,包括不恩那个访问实例Field和实例方法   与普通初始化块类似的是,系统在类初始化阶段执行静态初始化块时,不仅会执行本类的静态初始化块,而且还会一直上朔到java.lang.Object了,先执行java.lang.Object类的静态初始化块,然后执行器父类的静态初始化块,最后才执行该类的静态初始化块,经过这个过程,才完成了该类的初始化过程。只有当类初始化完成后,才可以在系统中使用这个类,包括访问这个类的类方法 类Field,或者用这个类来创建实例   下面程序创建了三个类:Root,Mid和Leaf,这三个类都提供了静态初始化块和普通初始化块,而且Mid类里还是用this调用重载的构造器,Leaf使用super显式调用其父类指定的构造器   class Root {     static {         System.out.println("Root的静态初始化块");     }     {         System.out.println("Root的普通初始化块");     }     public Root(){         System.out.println("Root 的无参数的构造器");     } } class Mid extends Root{     static {         System.out.println("Mid 的静态初始化块");     }     {         System.out.println("Mid  的普通初始块");     }     public Mid(){         System.out.println("Mid的无参数的构造器");     }     public Mid(String msg){         this();         System.out.println("Mid 的带参数构造器,其参数值: " + msg);     } } class Leaf extends Mid {     static{         System.out.println("Leaf的静态初始化块");     }     {         System.out.println("Leaf的普通初始化块");     }     public Leaf(){         super("疯狂Java讲义");         System.out.println("执行Leaf的构造器");     } } public class Test{     public static void main(String[] args){         new Leaf();         new Leaf();     } }   普通初始化块和构造器的执行顺序与前面介绍的一致,每次创建一个leaf对象时,都需要先执行最顶层父类的初始化块,构造器,然后执行其父类的初始化块,构造器,最后才执行Leaf类的初始化块和构造器   Java系统加载并初始化某个类时,总是保证该类的所有父类(包括直接父类和间接父类)全部加载并初始化。