java初始化顺序

来源:互联网 发布:linux ftp put命令 编辑:程序博客网 时间:2024/06/03 06:28

一、初始化顺序

在类的内部,变量的定义顺序先后决定了初始化的顺序。即使变量定义在不同的方法之间,它们也会在任何方法(包括构造函数)在调用之前初始化。

1.简单的初始化顺序:

class Sample {    Sample() {        System.out.println("Sample默认构造函数被调用");    }    Sample(String s) {        System.out.println(s);    }}public class JavaInit {    Sample sam1 = new Sample("sam1成员初始化");    JavaInit() {        System.out.println("JavaInit默认构造函数被调用");    }    Sample sam2 = new Sample("sam2成员初始化");    void print() {        System.out.println("print()");    }    public static void main(String[] args) {        JavaInit ji = new JavaInit();        ji.print();    }}

输出:
sam1成员初始化
sam2成员初始化
JavaInit默认构造函数被调用
print()

2、静态数据初始化:

public class JavaStaticInit {static Sample sam = new Sample("静态成员sam初始化");Sample sam1 = new Sample("sam1成员初始化");JavaStaticInit() {    System.out.println("JavaStaticInit默认构造函数被调用");}public static void main(String str[]) {    JavaStaticInit a = new JavaStaticInit();    JavaStaticInit a1 = new JavaStaticInit();}

输出:
静态成员sam初始化
sam1成员初始化
JavaStaticInit默认构造函数被调用
sam1成员初始化
JavaStaticInit默认构造函数被调用
由输出结果可以看到:只有在第一个JavaStaticInit对象被创建(或第一次的访问静态数据)的时候,它们才会被初始化,此后,静态对象不会被再次初始化。

3、静态块的初始化:

public class JavaStaticInit {static {    System.out.println("static 块 1  执行");}static Sample sam = new Sample("静态成员sam初始化");Sample sam1 = new Sample("sam1成员初始化");JavaStaticInit() {    System.out.println("JavaStaticInit默认构造函数被调用");}static {    System.out.println("static块执行");    Sample sam2 = new Sample("静态块内初始化sam成员变量");}public static void main(String str[]) {    JavaStaticInit a = new JavaStaticInit();    JavaStaticInit a1 = new JavaStaticInit();}

输出:
static 块 1 执行
静态成员sam初始化
static块执行
静态块内初始化sam成员变量
sam1成员初始化
JavaStaticInit默认构造函数被调用
sam1成员初始化
JavaStaticInit默认构造函数被调用

由此而知,对于静态成员(static块可以看成普通的一个静态成员,其并不一定在类初始化时首先执行)之间或者普通成员之间,其初始化顺序只与其在类定义中的顺序有关,和其他因素无关。

4.非静态实例初始化:

class Mug {    Mug(int mark) {        System.out.println("Mug(" + mark + ")");    }}public class Mugs {    Mug mug1;    Mug mug2;    Mug mug3;    Mug mug4;    {        mug1 = new Mug(1);        mug2 = new Mug(2);        System.out.println("mug1---------------------mug2");    }    Mugs() {        System.out.println("Mugs()");    }    Mugs(int mark) {        System.out.println("Mugs(" + mark + ")");    }    {        mug3 = new Mug(3);        mug4 = new Mug(4);        System.out.println("mug3---------------------mug4");    }    public static void main(String[] args) {        new Mugs();        new Mugs();    }}

输出:
Mug(1)
Mug(2)
mug1———————mug2
Mug(3)
Mug(4)
mug3———————mug4
Mugs()
Mug(1)
Mug(2)
mug1———————mug2
Mug(3)
Mug(4)
mug3———————mug4
Mugs()

二、继承下的初始化

class A {public static int a = 0;public int b = 0;Sample sam1 = new Sample("■父类 -普通变量-位置是构造函数前");static {    System.out.println("■父类 - 静态初始块 - 位置是构造函数前");}{    System.out.println("■父类 - 普通初始块 - 位置是构造函数前");}public A() {    System.out.println("■父类 - 构造函数");}static {    System.out.println("■父类 - 静态初始块 - 位置是构造函数后");}{    System.out.println("■父类 - 普通初始块 - 位置是构造函数后");}Sample sam2 = new Sample("■父类 -普通变量-位置是构造函数后");

}

class B extends A {
Sample sam1 = new Sample(“◆子类 -普通变量-位置是构造函数后”);
static {
System.out.println(“◆子类 - 静态初始块 - 位置是构造函数前”);
}
{
System.out.println(“◆子类 - 普通初始块 - 位置是构造函数前”);
}
public B() {
System.out.println(“◆子类 - 构造函数”);
}
static {
System.out.println(“◆子类 - 静态初始块 - 位置是构造函数后”);
}
{
System.out.println(“◆子类 - 普通初始块 - 位置是构造函数后”);
}
Sample sam2 = new Sample(“◆子类 -普通变量-位置是构造函数后”);
}

public class MS_Extends {    public static void main(String[] args) {        B b = new B();    }}

输出:
■父类 - 静态初始块 - 位置是构造函数前
■父类 - 静态初始块 - 位置是构造函数后
◆子类 - 静态初始块 - 位置是构造函数前
◆子类 - 静态初始块 - 位置是构造函数后
■父类 -普通变量-位置是构造函数前
■父类 - 普通初始块 - 位置是构造函数前
■父类 - 普通初始块 - 位置是构造函数后
■父类 -普通变量-位置是构造函数后
■父类 - 构造函数
◆子类 -普通变量-位置是构造函数后
◆子类 - 普通初始块 - 位置是构造函数前
◆子类 - 普通初始块 - 位置是构造函数后
◆子类 -普通变量-位置是构造函数后
◆子类 - 构造函数

由此可知,
1、按照顺序执行父类静态变量、静态块
2、按照顺序执行子类静态变量、静态块
3、按照顺序执行父类的普通变量、普通块、执行父类的构造函数
4、按照顺序执行子类的普通变量、普通块、执行子类的构造函数

三、总结:

1、 继承体系的所有静态成员初始化(先父类,后子类)
2、 父类初始化(普通成员的初始化–>构造函数的调用)
3 、子类初始化(普通成员–>构造函数)

初始化顺序图##一、

小知识点总结:
static{}(静态代码块)与{}(非静态代码块)的异同点
相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,
    一般在代码块中对一些static变量进行赋值。
不同点:静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。
    静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new
    一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码块不行

0 0