Reflection review summary and class initialization related interview questions

Posted by SlimSlyk on Fri, 03 Sep 2021 02:58:12 +0200

1, Review
1. Why use reflection?
In order to dynamically load a class at runtime and create its object, or call its members (member variables, member methods), or the details of a type.
Conversely, if reflection is not used, the type must be determined "at compile time".

2. Source of reflection (starting point): object of Class.

So understand:
The compiled code exists in the form of xx.class file on the "hard disk".
These codes must be "loaded" into memory before they can be used. In memory, each xxx.class file should be stored in memory as an object,
The type of this object is Class.

Each Java type  <==> Xx.class file or data
Class object  <==>   xx.class file or data
Class object   ==   A type

3. There are four ways to obtain Class objects
(1) Type name.class
(2) Instance object. getClass() of a type
(3) Class.forName("full name of type")
(4) Class loader object. loadClass("full name of type")

How to choose four methods?
First: if this type is known, determined and existing when writing the current code, you can directly   The type name. class is the most direct and simple
Second: if the type of an object is uncertain, but the object has a variable (usually the variable is of the parent class or parent interface type),
    At this time, if you need to obtain the runtime type of the object, select  ( 2)
Third: if this type is unknown, uncertain, or temporarily does not exist when writing the current code, you need to read. xml,. properties, annotation information, etc
To get the type name, use (3)
Fourth: generally, the method (4) is used only when the user-defined class loader or the bytecode file in a specific directory needs to be loaded.

4. Application of reflection
(1) Get class details
java.lang.Class class
Types under java.lang.reflect package:
    Package,Modifier,Constructor,Field,Method,Array....
java.lang.Annotation

(2) Dynamically create any type of object at runtime
A: Directly use Class object. newInstance()
    This approach requires that the type must have a public parameterless construct
B: First get the object of Constructor of type, and then use the Constructor object. newInstance(...)

(3) The runtime dynamically manipulates arbitrary member variables
To manipulate static variables:
A: Get Class object
B: Get the Field object of the static variable you want to operate on
C: Call the set/get method of the Field object
If the permission modifier of the member variable represented by the Field object is limited, setAccessible(true) of the Field object can be called

To manipulate non static variables:
A: Get Class object
B: Get the Field object of the static variable you want to operate on
C: Create an instance object of the type represented by the Class object
    For example, if the Class object represents the Student type, create the Student object
D: Call the set/get method of the Field object
If the permission modifier of the member variable represented by the Field object is limited, setAccessible(true) of the Field object can be called

(4) Call arbitrary methods dynamically at run time
To call a static method:
A: Get Class object
B: Get the Method object of the static Method you want to call
C: Call the invoke Method of the Method object
If the permission modifier of the static Method represented by the Method object is limited, setAccessible(true) of the Method object can be called

To call a non static method:
A: Get Class object
B: Get the Method object of the static Method you want to call
C: Create an instance object of the type represented by the Class object
    For example, if the Class object represents the Student type, create the Student object
D: Call the invoke Method of the Method object
If the permission modifier of the static Method represented by the Method object is limited, setAccessible(true) of the Method object can be called

(5) Gets information about the generic parent class at run time
(6) The runtime obtains the annotation information above a class, method, member variable, etc
(7) Dynamically use Array type to create and manipulate arrays
(8) The runtime obtains the internal class information or external class information of a class

5. Class loading
Loading steps of class:
(1) Loading
(2) Connection: check, prepare, parse
(3) Initialization
Result of Class loading: Class object
Class loader: class loader

Class loaders are divided into four levels:
(1) Boot class loader
(2) Extended class loader
(3) Application class loader (the class written by the programmer is basically loaded by it)
(4) Custom class loader

Working mode of class loader: parent delegation mode

public class TestReview {
    public static void main(String[] args) throws Exception {
        //(1) Gets a Class object of type int
        Class clazz1 = int.class;

        //(2) Obtain a java bean type under the com.atguigu.bean package. This type is uncertain. The specific class name can be determined through the info.properties file
        Properties properties = new Properties();//Create a collection object and container object to hold the key and value pairs read from info.properties
        properties.load(TestReview.class.getClassLoader().getResourceAsStream("info.properties"));
//        Class clazz2 = Class.forName(properties.getProperty("className"));


        Student s1 = new Student(1,"Zhang San");
        Student s2 = new Student(2,"Li Si");

        System.out.println(s1.equals(s2));
        System.out.println(s1.equals("Zhang San"));

    }


    public static void method(Object obj){
        //(3) Get the runtime type of obj object here
        Class<?> c3 = obj.getClass();
    }
}

class Student{
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()){
            System.out.println("Inconsistent type");
            return false;
        }
        System.out.println("The types are the same Student object");
        Student student = (Student) o;
        return id == student.id &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

Some class loading processes do not immediately trigger class initialization.
(1) Use a static constant of a class
(2) If a static member of a parent class is called through a subclass, the subclass will not initialize, but the parent class will be initialized.
(3) Use a class to declare an array and create an array object, but the element object has not been created

In addition to these three cases, the use of classes will immediately trigger class initialization.
(1) Create an object of this class
(2) Call the static member of this class
(3) Use a class through reflection
(4) If a subclass is used, the initialization of the parent class will be triggered when the subclass is initialized
(5) The class where the main method is located must be initialized before running main

public class TestExam {
    static{
        System.out.println("main Static code block of the class in which the method is located");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println(MyClass.MAX_VALUE);//100

        Son.method();//Call the static method of the parent class through the subclass name

        MyClass[] arr = new MyClass[5];//A new type MyClass [] type is generated. Initialize this new type
        arr[0] = new MyClass();

        Class.forName("com.atguigu.review.Son");//Causes the Son class to initialize

    }
}
class MyClass{
    public static final int MAX_VALUE = 100;

    static {
        System.out.println("MyClass Static code block");
    }
}
class Father{
    static {
        System.out.println("1.Static code block of the parent class");
    }
    public static void method(){
        System.out.println("2.Static method of parent class");
    }
}
class Son extends Father{
    static {
        System.out.println("3.Static code block of subclass");
    }
}

Topics: Java