📜  Java中初始化块和构造函数的执行顺序

📅  最后修改于: 2022-05-13 01:54:37.017000             🧑  作者: Mango

Java中初始化块和构造函数的执行顺序

先决条件:静态块,初始化块,构造函数
在Java程序中,可以对方法、构造函数和初始化块执行操作。
实例初始化块:IIB 用于初始化实例变量。 IIB 在构造函数之前执行。每次创建类的对象时它们都会运行。
Initializer 块:包含在创建实例时始终执行的代码。它用于声明/初始化类的各种构造函数的公共部分。
构造函数:用于初始化对象的状态。与方法一样,构造函数也包含在创建对象时执行的语句(即指令)集合。

Java中初始化块和构造函数的执行顺序

  1. 每当类第一次在 JVM 中加载时,静态初始化块就会运行
  2. 初始化块按照它们在程序中出现的顺序运行。
  3. 每当初始化类并且在调用构造函数之前执行实例初始化块。它们通常放置在大括号内的构造函数上方。
// Java code to illustrate order of
// execution of constructors, static
// and initialization blocks
class GFG {
  
    GFG(int x)
    {
        System.out.println("ONE argument constructor");
    }
  
    GFG()
    {
        System.out.println("No  argument constructor");
    }
  
    static
    {
        System.out.println("1st static init");
    }
  
    {
        System.out.println("1st instance init");
    }
  
    {
        System.out.println("2nd instance init");
    }
  
    static
    {
        System.out.println("2nd static init");
    }
  
    public static void main(String[] args)
    {
        new GFG();
        new GFG(8);
    }
}

输出

1st static init
2nd static init
1st instance init
2nd instance init
No  argument constructor
1st instance init
2nd instance init
ONE argument constructor

注意:如果有两个或多个静态/初始化程序块,那么它们将按照它们在源代码中出现的顺序执行。

现在,预测以下程序的输出 -

// A tricky Java code to predict the output
// based on order of 
// execution of constructors, static 
// and initialization blocks
class MyTest {
    static
    {
        initialize();
    }
      
    private static int sum;
      
    public static int getSum()
    {
        initialize();
        return sum;
    }
  
    private static boolean initialized = false;
  
    private static void initialize()
    {
        if (!initialized) {
            for (int i = 0; i < 100; i++)
                sum += i;
            initialized = true;
        }
    }
}
  
public class GFG {
    public static void main(String[] args)
    {
        System.out.println(MyTest.getSum());
    }
}

输出:

9900

解释:

  • 初始化函数中的循环从 0 到 99。考虑到这一点,您可能会认为程序会打印从 0 到 99 的数字的总和。因此 sum 是 99 × 100 / 2 或 4、950。然而,该程序, 不以为然。它打印9900 ,完全是这个值的两倍。
  • 要了解它的行为,让我们跟踪它的执行情况。GFG.main 方法调用 MyTest.getSum。在执行 getSum 方法之前,VM 必须初始化类 MyTest。类初始化按照它们在源代码中出现的顺序执行静态初始化程序。
  • MyTest 类有两个静态初始化器:类顶部的静态块和已初始化的静态字段的初始化。该块首先出现。它调用方法initialize,该方法测试已初始化的字段。由于尚未为该字段分配任何值,因此它具有默认布尔值 false。
  • 类似地,sum 的默认 int 值是 0。因此,initialize 方法执行您所期望的操作,将 4, 950 添加到 sum 并将 initialized 设置为 true。静态块执行后,已初始化字段的静态初始化器将其设置回 false,从而完成 MyTest 的类初始化。不幸的是,sum 现在包含 4950,但 initialized 包含 false。
  • 然后 GFG 类中的 main 方法调用 MyTest.getSum,后者又调用 initialize 方法。因为初始化标志为假,所以initializeIf方法进入了它的循环,在sum的值上再增加4, 950,将它的值增加到9, 900。getSum方法返回这个值,程序打印出来