Java中类的初始化顺序

时间:2021-02-18 08:43:10

一、一个类的初始化顺序(没继承情况)

 规则:

1.静态变量>普通变量>构造方法

  2.变量定义的顺序决定初始化的顺序

3.静态变量和静态块是一样的,普通变量和非静态块是一样的,即能够把静态块看作是静态变量。把非静态块看作是普通变量

public class Test1 {
public static void main(String[] args) {
new D();
}
} class C{
public C(String s){
System.out.println(s);
}
} class D{
/* D的构造方法 */
public D(){
System.out.println("D的构造方法");
} /* D的非静态变量 */
private C c1 = new C("变量1");
private C c2 = new C("变量2"); /* D的静态变量 */
private static C c3 = new C("静态变量1");
private static C c4 = new C("静态变量2"); /* D的静态初始化块 */
static{
System.out.println("D的静态初始化块。 。");
} /* D的实例初始化块 */
{
System.out.println("D的实例初始化块。。");
}
}

运行结果:

静态变量1

静态变量2

D的静态初始化块。

变量1

变量2

D的实例初始化块。



D的构造方法

二、一个类的初始化顺序(有继承情况)

规则:

  1.父类的初始化>子类的初始化

  2.静态变量>普通变量>构造方法

  3.变量定义的顺序决定初始化的顺序

  4.静态变量和静态块是一样的,普通变量和非静态块是一样的。即能够把静态块看作是静态变量,把非静态块看作是普通变量

public class Test2 {

	public static void main(String[] args) {
new B();
}
} class Feild{
public Feild(String s){
System.out.println(s);
}
} class A{
/* A的构造方法 */
public A(){
System.out.println("父类的构造方法");
} /* A的非静态变量 */
private Feild f1 = new Feild("父类变量1");
private Feild f2 = new Feild("父类变量2"); /* A的静态变量 */
private static Feild f3 = new Feild("父类静态变量1");
private static Feild f4 = new Feild("父类静态变量2"); /* A的静态初始化块 */
static{
System.out.println("父类的静态初始化块。。 ");
} /* A的实例初始化块 */
{
System.out.println("父类的实例初始化块。 。");
}
} class B extends A{
/* B的构造方法 */
public B(){
System.out.println("子类的构造方法");
} /* B的非静态变量 */
private Feild f5 = new Feild("子类变量1");
private Feild f6 = new Feild("子类变量2"); /* B的静态变量 */
private static Feild f7 = new Feild("子类静态变量1");
private static Feild f8 = new Feild("子类静态变量2"); /* B的静态初始化块 */
static{
System.out.println("子类的静态初始化块。。");
} /* B的实例初始化块 */
{
System.out.println("子类的实例初始化块。。");
}
}

运行结果:

父类静态变量1

父类静态变量2

父类的静态初始化块。。

子类静态变量1

子类静态变量2

子类的静态初始化块。。

父类变量1

父类变量2

父类的实例初始化块。。

父类的构造方法

子类变量1

子类变量2

子类的实例初始化块。。

子类的构造方法

以下再看一个样例:

public class Test1 {
public static void main(String[] args) {
new D();
}
} class D{
/* D的构造方法 */
public D(){
System.out.println("D的构造方法");
} public D(String s){
System.out.println(s);
} /* D的非静态变量 */
private static D d1 = new D("变量1");
private static D d2 = new D("变量2"); /* D的静态初始化块 */
static{
System.out.println("D的静态初始化块。 。");
} /* D的实例初始化块 */
{
System.out.println("D的实例初始化块。 。 ");
}
}

输出结果为:

D的实例初始化块。。

变量1

D的实例初始化块。。

变量2

D的静态初始化块。



D的实例初始化块。

D的构造方法

解析:由于new D()时,类D里面会创建两个实例。而又由于静态块的位置在两个实例创建的后面,所以不会先输出静态块的内容。而是创建了两个实例d1、d2后,再new D()。这时才运行静态块、实例块、构造方法。

以下将静态块移到d1和d2创建之前:

public class Test1 {
public static void main(String[] args) {
new D();
}
} class D{
/* D的构造方法 */
public D(){
System.out.println("D的构造方法");
} public D(String s){
System.out.println(s);
} /* D的静态初始化块 */
static{
System.out.println("D的静态初始化块。 。");
} /* D的非静态变量 */
private static D d1 = new D("变量1");
private static D d2 = new D("变量2"); /* D的实例初始化块 */
{
System.out.println("D的实例初始化块。。 ");
}
}

输出结果例如以下:

D的静态初始化块。。

D的实例初始化块。

变量1

D的实例初始化块。。

变量2

D的实例初始化块。。

D的构造方法