Initialization of the class loading process (10)

initialization

The initialization of the class is the last step of class loading. In the preparation phase, the variables in the class are the initial values ​​specified by the system, and will be carried out according to the program in the initialization phase.
More direct expression: the initialization phase is to execute the class constructor <clinit> () method process .

The generation of the <clinit >() method: it
is generated by the compiler automatically collecting the assignment action of all class variables in the class and the statement in the static statement block (static{} block). The compiler collection order is determined by the order in which the statements appear in the source file. The static statement block can only access variables defined before the static statement block, and the variables defined after it can be assigned to the previous static statement block. But it cannot be accessed.

public class Test{
    
    
	static{
    
    
		i = 0; //变量赋值可以正常编译通过
		System.out.print(i);//编译器会提示 “非法向前引用”
	}
	static int i = 1;// 定义在静态语句快之后的变量
}

The <clinit >() method is different from the class construction method (<init>()). It does not need to explicitly call the constructor of the parent class. The Java virtual machine ensures that the parent The <clinit >() of the class has been executed. Therefore, the type of the first <clinit >() method executed in the Java virtual machine must be java.lang.Object.

Since the <clinit >() method of the parent class is executed first, the static statement block defined in the parent class is better than the variable assignment operation of the child class.
E.g:

  static class Parent{
    
    
  public static int A = 1;
  static{
    
    
  		A = 2;
	}
}

static class Sub extends Parent{
    
    
	public static int B = A;
}

public static void main(String[] args){
    
    
	System.out.print(Sub.B);
}

输出的为2不为1
  • The <clinit >() method is not necessary for classes and interfaces. If a class does not have a static statement block and no variable assignment operation, then the compiler does not need to generate a <clinit >() method for this class.
  • Static code blocks cannot be used in the interface, and there are still variable assignment operations. The interface execution <clinit >() method does not need to execute the parent interface <clinit >() method first, because only when the variables defined by the parent interface are used For the initialization of the parent interface, the implementation class of the interface will not execute the <clinit >() method of the interface when it is initialized.
  • The Java virtual machine must ensure that a class <clinit >() method is correctly locked and synchronized in a multithreaded environment. If multiple threads initialize a class, other threads will enter the blocking queue, which may cause process blocking.
    Note: Although other threads will be blocked, if the thread that executes the <clinit >() method exits this method, other threads will not enter the method after waking up. Under the same class loader, one type only Will be initialized once.

Guess you like

Origin blog.csdn.net/weixin_43663421/article/details/109299696