关于静态代码块,和构造代码块执行时机

以下内容仅供本人学习记录所用!!!以下测试都在JDK8下完成

一、关于静态代码块的执行时机(以下情况都是在静态代码块未曾执行过的情况下)

 1. 首次对类进行实例化时

 2. 调用该类的静态成员时
    例外:
       Ⅰ.final修饰的静态成员字符串常量。
          即是final static String a="dfsaf"这类型的变量
          因为调用这种字符串成员常量时编译器会直接优化成字符串而未对类产生调用
       Ⅱ.final修饰的静态成员基本数据类型
       注意:使用final static String a=new String("dfsaf")和在静态代码块中赋初值的成员不在此例
       外之中。

 3. 使用Class.forName()对类进行加载时(不包括参数initialize为false的情况下)

 4. 其子类做以上三个操作时也会对其的静态代码块进行调用。

二、构造代码块的执行时机

 1. 每次执行构造函数之前执行

三、关于一个类加载成员的顺序

 1. 静态成员属性初始化(有且只有一次),静态代码块(有且只有一次)。由上到下的执行顺序,即谁在上面就先执行谁。
 2. 普通成员属性初始化,构造代码块。由上到下的执行顺序。
 3. 构造方法

下面上代码

public class ClassB {

    private final static Test staticTest=new Test("B 静态成员属性初始化");

    private Test testFeild=new Test("B 普通成员属性初始化");

    public final static String FINAL_STRING="FINAL_STRING";

    public final static int FINAL_INT=1;

    static {
        System.out.println("B 静态代码块执行完成");
    }

    {
        System.out.println("B 构造代码块执行完成");
    }

    public ClassB() {
        System.out.println("B 构造方法执行完成");
    }

}

成员属性类

public class Test {

    public Test(String str) {
        System.out.println(str);
    }

}

测试类

不做任何ClassB类的调用

public class TestStaticBlock {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println("test begin...");
        System.out.println("test end...");
    }
}

输出结果

test begin...
test end...

以上结果说明静态代码块还有静态属性在默认情况并且未曾关联调用时是不会自动调用或初始化的

调用final修饰的常量字符串和基本数据类型

public class TestStaticBlock {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println("test begin...");
        System.out.println(ClassB.FINAL_INT);//调用基础数据类型常量
        System.out.println(ClassB.FINAL_STRING);//调用字符串常量
        System.out.println("test end...");
    }
}

输出结果

test begin...
1
FINAL_STRING
test end...

以上结果证明静态代码块执行时机第二点中的例外情况

在实例化一个对象时各成员的初始化调用顺序

public class TestStaticBlock {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println("test begin...");
        new ClassB();
        System.out.println("------------");
        new ClassB();
        System.out.println("test end...");
    }
}

输出结果

test begin...
B 静态成员属性初始化
B 静态代码块执行完成
B 普通成员属性初始化
B 构造代码块执行完成
B 构造方法执行完成
------------
B 普通成员属性初始化
B 构造代码块执行完成
B 构造方法执行完成
test end...

将静态属性和成员属性的位置调到类的最下面类结构为

public class ClassB {

    public final static String FINAL_STRING="FINAL_STRING";

    public final static int FINAL_INT=1;

    static {
        System.out.println("B 静态代码块执行完成");
    }

    {
        System.out.println("B 构造代码块执行完成");
    }

    public ClassB() {
        System.out.println("B 构造方法执行完成");
    }

    private Test testFeild=new Test("B 普通成员属性初始化");

    private final static Test staticTest=new Test("B 静态成员属性初始化");

}

再次进行执行产生的结果

test begin...
B 静态代码块执行完成
B 静态成员属性初始化
B 构造代码块执行完成
B 普通成员属性初始化
B 构造方法执行完成
------------
B 构造代码块执行完成
B 普通成员属性初始化
B 构造方法执行完成
test end...

以上结果显示出一个类的执行顺序

四、关于枚举对象(实例化)还有枚举中静态代码块的执行时机(默认情况下是未曾关联调用或访问是不会自动执行或实例化的)

 枚举的对象实例化(每个对象各执行一次)和静态代码块执行,有且只有一次
 1. 使用或获取(使用枚举类的valueOf相关方法)枚举实例对象时
 2. 调用枚举静态成员时,例外和上面静态代码块的一致
 3. 使用Class.forName()对类进行加载时(不包括参数initialize为false的情况下)

枚举执行或初始化成员的顺序


 1. 构造代码块,成员属性。由上到下的顺序
 2. 构造函数
    以上两步有几个枚举对象就重复执行几次
 3. 静态成员包括静态代码块。由上到下的顺序

下面上代码

枚举类

public enum TestEuum {

    INSTANTS,TWO;

    public static Test staticTest=new Test("枚举静态属性初始化完成");

    public static final String FINAL_STRING="FINAL_STRING";

    public static final int FINAL_INT=1;

    TestEuum(){
        System.out.println("枚举构造函数执行完成");
    }

    static {
        System.out.println("枚举静态代码块执行完成");
    }

    {
        System.out.println("枚举构造代码块执行完成");
    }

    public static void staticMethod(){
        System.out.println("枚举静态方法执行完成");
    }



    private Test Test=new Test("枚举成员属性初始化完成");


}

不做任何调用测试

public class TestStaticBlock {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println("test begin...");
        System.out.println("test end...");
    }
}

执行结果

test begin...
test end...

以上结果可以看出未曾主动调用相关属性或方法枚举是不会主动实例化和执行静态代码块的

调用枚举的字符串常量和基本数据常量测试

public class TestStaticBlock {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println("test begin...");
        System.out.println(TestEuum.FINAL_INT);//调用枚举基本数据常量
        System.out.println(TestEuum.FINAL_STRING);//调用枚举字符串常量
        System.out.println("test end...");
    }
}

执行结果

test begin...
1
FINAL_STRING
test end...

以上结果可以看出例外情况,并未使枚举实例化对象和执行静态代码块

测试调用枚举对象

public class TestStaticBlock {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println("test begin...");
        System.out.println(TestEuum.INSTANTS);
        System.out.println("test end...");
    }
}

执行结果

test begin...
枚举构造代码块执行完成
枚举成员属性初始化完成
枚举构造函数执行完成
枚举构造代码块执行完成
枚举成员属性初始化完成
枚举构造函数执行完成
枚举静态属性初始化完成
枚举静态代码块执行完成
INSTANTS
test end...

以上结果可以看出会将所有的枚举对象实例化出来才会初始化静态属性和执行静态代码块

调整静态成员属性和成员属性的位置上面类的加载顺序已经测试过这里不再进行测试。

调用静态成员的测试和获取枚举对象触发枚举实例化和执行枚举静态代码块就不在上代码了。

你可能感兴趣的:(java基础)