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系统加载并初始化某个类时,总是保证该类的所有父类(包括直接父类和间接父类)全部加载并初始化。