Java static语句块变量,普通语句块,构造函数的执行顺序

it2022-05-05  145

   最近经常遇到static语句块的问题,查了些资料增强了理解,这里借例子总结一下。

1 public class Test1 { 2 public static int X=100; 3 public final static int Y=200; 4 public Test1(){ 5 System.out.println("Test构造函数执行"); 6 } 7 static{ 8 System.out.println("static语句块执行"); 9 } 10 11 { 12 System.out.println("not static 语句块执行"); 13 } 14 15 public static void display(){ 16 System.out.println("静态方法被执行"); 17 } 18 public void display_1(){ 19 System.out.println("实例方法被执行"); 20 } 21 22 public static void main(String [] args){ 23 Test1.display(); 24 System.out.println("x=" + Test1.X + " y=" + Test1.Y ); 25 Test1.display(); 26 Test1 t1 = new Test1(); 27 Test1 t2 = new Test1(); 28 System.out.println("X=" + t1.X + " Y=" + t1.Y); 29 Test1.display(); 30 } 31 } 运行结果如下: static语句块执行 静态方法被执行 x=100 y=200 静态方法被执行 not static 语句块执行 Test构造函数执行 not static 语句块执行 Test构造函数执行 X=100 Y=200 静态方法被执行

    可以看出static代码块是在类加载时自动执行的且只执行一次,非静态代码块在创建对象自动执行的代码,不创建对象不执行该类的非静态代码块。 顺序为 静态代码块--》非静态代码块--》类构造方法。第一次创建类实例、调用静态方法、访问静态变量或使用用Class.forName()显示加载类的时候都会执行static语句块。另外有多个static语句块时按顺序执行

如在第一个static语句块之后再添加一个static语句块

static{         System.out.println("static语句块执行");     }     static{         System.out.println("static222语句块执行");     } 运行结果为: static语句块执行 static222语句块执行 静态方法被执行 x=100   y=200

另外,在Java类中静态变量的初始化顺序和静态变量的声明顺序是一致的。为了验证该说法,我们写一个简单的小程序,代码如下:

public class StaticParams { private static int NUM_A = getA(); private static int NUM_B = getB(); private static List<String> LIST_A = getListA(); private StaticParams() { System.out.println("初始化构造方法"); } public static StaticParams getInstance() { return new StaticParams(); } private static int getA() { System.out.println("初始化A"); return 10; } private static int getB() { System.out.println("初始化B"); return 20; } private static List<String> getListA() { System.out.println("初始化List"); return new ArrayList<String>(); } public static void main(String[] args) { StaticParams.getInstance(); } } 运行结果如下: 初始化A 初始化B 初始化List 初始化构造方法

调整静态变量NUM_A和NUM_B的声明顺序,其他逻辑不变,然后再次运行该程序,输出结果如下:

private static int NUM_B = getB(); private static int NUM_A = getA(); private static List<String> LIST_A = getListA(); 运行结果如下:      初始化B      初始化A      初始化List      初始化构造方法

如果在某个静态变量的初始化还未执行之前就使用该静态变量,就会抛出 ExceptionInInitializerError 异常,表明在计算静态初始值或静态变量的初始值期间发生异常。。为了模拟该问题产生原因,我们修改上面的代码成一个单例模式,具体代码如下:

public class StaticParams { private static StaticParams sp = buildStaticParams(); private static int NUM_A = getA(); private static int NUM_B = getB(); private static List<String> LIST_A = getListA(); /** * 私有化构造方法 */ private StaticParams() { System.out.println("初始化构造方法"); } /** * sp的声明在其他几个静态变量之前 * * @return */ private static StaticParams buildStaticParams() { if (null == sp) { sp = new StaticParams(); } int result = NUM_A * NUM_B; // 基本类型有默认值,此处不会报错,但结果不正确 System.out.println("result is :" + result); LIST_A.add("abcd"); //此时LIST_A还未初始化,到此有异常 return sp; } /** * 获取StaticParams实例 * * @return */ public static StaticParams getInstance() { return sp; } private static int getA() { System.out.println("初始化A"); return 10; } private static int getB() { System.out.println("初始化B"); return 20; } private static List<String> getListA() { System.out.println("初始化List"); return new ArrayList<String>(); } public static void main(String[] args) { StaticParams.getInstance(); } }

在上面的例子中,sp变量初始化中使用到的其他的变量,但其他的静态变量还未初始化,故而在sp初始化时就会产生上面的异常,运行上面的程序就可以在控制台看到ExceptionInInitializerError 异常警告。

参考文章:https://blog.csdn.net/u010397369/article/details/16810863

https://blog.csdn.net/madaidao/article/details/46738369

 


最新回复(0)