When class initialization occurs

class initialization

prerequisite knowledge

Class loading phase :

  1. Loading: Find the class bytecode file of the class (.class file compiled from the .java file), convert the static storage structure of the file into the runtime data structure of the method area , and use the file to create a java.lang.Class Object, stored in the Java heap, the data structure of the object reference method area
  2. Verification: Check the correctness of the loaded class file
  3. Prepare
    • Static variable allocation and assignment are two steps, the allocation of space is completed in the preparation phase, and the assignment is completed in the initialization phase
    • If the static variable is a final basic type and a string constant , the value in the compilation phase is determined, and the assignment is completed in the preparation phase
    • If the static variable is final, but belongs to the reference type, then the assignment will also be done during the initialization phase
  4. Parsing: The symbolic quotes in the constant pool are parsed into direct references, and symbolic references are understood as an identifier, while direct references directly point to addresses in memory
  5. Initialization: perform initialization on static variables and static code blocks

The above five stages do not start the next step after executing the previous step, that is, it does not necessarily initialize immediately after loading

Distinguish between class initialization and object initialization

  • Class initialization: It is one of the steps in the class loading phase, and it is the initialization of static variables and static code blocks
  • The initialization of the object generally occurs in the process of calling the constructor of the new instance object
//用一个例子来说明
class User {
    
    
    private int age;
    private String name;

    static {
    
    
        System.out.println("user类初始化");
    }
    User(){
    
    
        System.out.println("user对象无参方式初始化");
    }
    User(int age, String name){
    
    
        this.age = age;
        this.name = name;
        System.out.println("user对象有参方式初始化");
    }
}

public class ClassLoader {
    
    
    static {
    
    
        System.out.println("main方法所在类初始化");
    }
    public static void main(String[] args) {
    
    
        System.out.println("开始执行main方法");
        User user = new User();
        System.out.println("第二次new一个user对象------------------------------");
        User user1 = new User();
	}
}


/*
Operation result:
Initialize the class where the main method is located
Start to execute the main method
user class initialize
the user object without parameters Initialize
the second new user object ------------------ ----------
The user object is initialized without parameters

Analysis : The initialization of the class where main is located always happens first, and the class initialization only happens once
*/

When class initialization occurs

Class initialization is [ lazy ]

  • The class where the main method is located will always be initialized first

    • The corresponding example corresponds to the above code
  • When accessing a static variable or static method of this class for the first time


class User {
    
    
    private int age;
    private String name;
    static String element = "user类的静态变量";
    
    static {
    
    
        System.out.println("user类初始化");
    }
    User(){
    
    
        System.out.println("user对象无参方式初始化");
    }
    User(int age, String name){
    
    
        this.age = age;
        this.name = name;
        System.out.println("user对象有参方式初始化");
    }
}

public class ClassLoader {
    
    
    static {
    
    
        System.out.println("main方法所在类初始化");
    }
    public static void main(String[] args) {
    
    
        System.out.println("开始执行main方法");
        //调用user类的静态变量 ,发生user类的初始化
        System.out.println(User.element);
        System.out.println("第二次调用类的静态变量---------");
        System.out.println(User.element);
	}
}

/*
Operation results:
The class where the main method is located is initialized
Start to execute the main method
user class to initialize
the static variables of the user class
The second call to the static variables of the class --------- Static variable analysis
of the user class : the first visit to this class The class will be initialized only when the static variable or static method of the class is static, and the class initialization will only happen once */ Before illustrating the timing of the following two class initialization, first explain the process of subclass initialization



class User {
    
    
    private int age;
    private String name;
    static String element = "user类的静态变量";

    {
    
    
        System.out.println("user对象代码块");
    }
    static {
    
    
        System.out.println("user类初始化");
    }
    User(){
    
    
        System.out.println("user对象无参方式初始化");
    }
    User(int age, String name){
    
    
        this.age = age;
        this.name = name;
        System.out.println("user对象有参方式初始化");
    }
}
class Student extends User{
    
    

    {
    
    
        System.out.println("student对象代码块");
    }
    static {
    
    
        System.out.println("student类初始化");
    }
    Student(){
    
    
        System.out.println("student对象无参方式初始化");
    }
    Student(int age, String name){
    
    
        System.out.println("student对象有参方式初始化");
    }


}

public class ClassLoader {
    
    
    static {
    
    
        System.out.println("main方法所在类初始化");
    }
    public static void main(String[] args) {
    
    
        System.out.println("开始执行main方法");
        Student student = new Student();

	}
}

/*
Operation result:
The class where the main method is located is initialized and
the main method is started. The user
class is initialized
. The student class is initialized. The user object code block
is initialized with no parameters. : The initialization of the parent class occurs first, and then the initialization of the subclass. The parent class object is generated, and then the subclass object is generated. Before the object is initialized, the content of the object itself will be processed, corresponding to the user object code block, and the initialization of the object occurs at the end */





  • Subclass initialization, if the parent class has not been initialized, it will trigger the initialization of the parent class

class User {
    
    
    private int age;
    private String name;
    static String element = "user类的静态变量";

    {
    
    
        System.out.println("user对象代码块");
    }
    static {
    
    
        System.out.println("user类初始化");
    }
    User(){
    
    
        System.out.println("user对象无参方式初始化");
    }
    User(int age, String name){
    
    
        this.age = age;
        this.name = name;
        System.out.println("user对象有参方式初始化");
    }
}
class Student extends User{
    
    

    {
    
    
        System.out.println("student对象代码块");
    }
    static {
    
    
        System.out.println("student类初始化");
    }
    Student(){
    
    
        System.out.println("student对象无参方式初始化");
    }
    Student(int age, String name){
    
    
        System.out.println("student对象有参方式初始化");
    }


}

public class ClassLoader {
    
    
    static {
    
    
        System.out.println("main方法所在类初始化");
    }
    public static void main(String[] args) {
    
    
        System.out.println("开始执行main方法");
        System.out.println("user类-----------");
        User user = new User();
        System.out.println("student类-----------");
        Student student = new Student();

	}
}

/*
Run result:
The class where the main method is located is initialized
Start to execute the main method
user class -----------
user class initializes
user object code block user object initializes student class
with no parameters --------
---
student class initialization
user object code block
user object initialization without parameter method
student object code block
student object initialization without parameter method
can see the subclass initialization, the parent class has been initialized, so the user class, that is, the parent class, does not need to be initialized

If the main method is
System.out.println ("Start executing the main method");
System.out.println ("student class -----------");
Student student = new Student();
Running results:
The class where the main method is located is initialized
Start to execute the main method
student class -----------
user class initialization
student class initialization
user object code block
user object no parameter initialization
student object code block
student object no parameter method Initialization
**Analysis: **Subclass initialization, if the parent class has not been initialized, it will trigger the initialization of the parent class
*/

  • When a subclass accesses the static variables of the parent class, it will only trigger the initialization of the parent class
public class ClassLoader {
    
    
    static {
    
    
        System.out.println("main方法所在类初始化");
    }
    public static void main(String[] args) {
    
    
        System.out.println("开始执行main方法");
        System.out.println(Student.element);
	}
}

/*
Operation result:
The class where the main method is located is initialized
Start to execute the main method
user class to initialize
the static variables of the user class
*/

Cases that do not result in class initialization

  • Accessing static final static constants (primitive types and strings) of a class does not trigger initialization
//将user类中的element设置为final
final static String element = "user类的静态变量";
public class ClassLoader {
    
    
    static {
    
    
        System.out.println("main方法所在类初始化");
    }
    public static void main(String[] args) {
    
    
        System.out.println("开始执行main方法");
        System.out.println(User.element);
    }
}

/*
Operation result:
The class where the main method is located is initialized, and the static variable of the user class of
the main method is started to be executed */

doubt:

  1. When a class is loaded from a class file into memory, is the data of the class stored in the method area?
    • The static variable or static method of the class is stored in the method area . After loading the class from the class file, a class object is created and stored in the heap to reference the static data structure of the class.
  2. After the initialization of the class, the initialization process of the object
    • If the class has not been loaded, it will be loaded into memory first
    • If the class has not been initialized, the class will be initialized first (if the parent class is not initialized, then the parent class will be initialized first)
    • Object initialization: first initialize the parent class object and then initialize the subclass
      • Open up space in the heap memory and allocate memory addresses
      • Create the unique properties of the object in the heap memory and perform default initialization (the reference type is null)
      • Initialize the properties (if the .java file has originally assigned some properties, for example, in the user classprivate String name =“java”;
      • Initialize the construction code block
      • Initialize the constructor
      • Assign a memory address to a variable in stack memory

Guess you like

Origin blog.csdn.net/weixin_47407737/article/details/126682601