[Java basic learning notes] reflection

reflex

Basic introduction to reflection

  1. Reflection can control the program through external file configuration without modifying the source code, which also conforms to the ocp principle of design mode (opening and closing principle: do not modify the source code, expansion function)

  2. Reflection mechanism:

    Reflection mechanism allows the program to obtain the internal information of any class (such as member variables, constructors, member methods, etc.) with the help of reflection API during execution, and can operate the properties and methods of objects. Reflection will be used at the bottom of design patterns and frameworks

    After loading the Class, an object of Class type is generated in the heap (there is only one Class object in a Class). This object contains the complete structure information of the Class, and the structure of the Class is obtained through this object

  3. The reflection mechanism can complete:

    (1) Determine the class of any object at run time

    (2) Construct an object of any class at run time

    (3) Get the member variables and methods of any class at run time

    (4) Call the member variables and methods of any object at run time

    (5) Generate dynamic proxy

  4. Reflection related classes:

    (1)java.lang.Class: represents a Class, and the Class object represents the object in the heap after a Class is loaded

    (2)java.lang.reflect.Method: represents the method of the class

    (3)java.lang.reflect.Field: represents the member variable of the class

    (4)java.lang.reflect.Constructor: represents the construction method of the class

    These classes are in Java Lang.reflection package

  5. Reflection can dynamically create and use objects, which can be used flexibly, but the prosperous use is basically to explain the execution, which has an impact on the execution speed

  6. Reflection call Optimization:

    (1)Method, Field and Constructor objects all have setAccessible() methods

    (2)setAccessible is a switch that enables and disables access security checks

    (3) If the parameter value is true, it means that the reflected object cancels the access check when in use to improve the reflection efficiency. If the parameter value is false, it means that the reflected object performs access check

Class class

  1. Class class

    (1)Class is also a class, so it inherits the Object class

    (2)Class objects are not new, but created by the system

    (3) For the Class object of a Class, there is only one copy in memory, because the Class is loaded only once

    (4) Each Class instance will remember which Class instance it was generated from

    (5) Through Class, you can get the complete structure of a Class through a series of API s

    (6)Class objects are stored in the heap

    (7) The bytecode binary data of a class is placed in the method area. In some places, it is called the metadata of the class (including method code, variable name, method name, access permission, etc.)

  2. Class common methods

    /**
     * Demonstrate common methods of Class
     */
    public class ClassMethod {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
            String classAllPath = "class_.Car";
            //1. Get the object corresponding to Car class
            Class<?> cls = Class.forName(classAllPath);
            System.out.println(cls);//Show cls object class_ Car
            System.out.println(cls.getClass());//Output cls run type Java lang.Class
            //2. Get package name
            System.out.println(cls.getPackage().getName());
            //3. Get the full class name
            System.out.println(cls.getName());
            //4. Create object instances through cls
            Object o = cls.newInstance();//You can create Object objects
            Car car = (Car)cls.newInstance();//You can also create Car objects
            System.out.println(car);//car.toString()
            //5. Acquire data through reflection
            Field f = cls.getField("brand");
            System.out.println(f.get(car));//Private properties cannot be accessed
            //6. Assign values to attributes by reflection
            f.set(car,"Benz");
            System.out.println(f.get(car));
            //8. Get all attributes
            Field[] fields = cls.getFields();
            for (Field field : fields){
                System.out.println(field.getName());
            }
        }
    }
    
  3. Six ways to get Class objects

    /**
     * Demonstrate how to get the Class object
     */
    public class GetClass {
        public static void main(String[] args) throws ClassNotFoundException {
            //1. The full Class name of a Class is known, and the Class is under the Class path, which can be obtained through the static method forName() of Class
            //Application scenario: it is mostly used for configuration files, reading the full path of classes and loading classes
            String classAllPath = "class_.Car";
            Class cls1 = Class.forName(classAllPath);
            System.out.println(cls1);
    
            //2. If a specific class is known, it can be obtained through the class of the class. This method is the most safe and reliable, and the program performance is the highest
            //Application scenario: it is mostly used for parameter transfer, such as obtaining the corresponding constructor object through reflection
            Class cls2 = Car.class;
            System.out.println(cls2);
    
            //3. If the instance of a Class is known, call the getClass() method of the instance to get the Class object
            //Application scenario: get the Class object by creating a good object
            Car car = new Car();
            Class cls3 = car.getClass();
            System.out.println(cls3);
    
            //4. The Class loader gets the Class object
            //(1) Get class loader
            ClassLoader classLoader = car.getClass().getClassLoader();
            //(2) Get the Class object through the Class loader
            Class cls4 = classLoader.loadClass(classAllPath);
            System.out.println(cls4);
    
            //Cls1, cls2, cls3 and cls4 are actually the same object
            System.out.println(cls1.hashCode());
            System.out.println(cls2.hashCode());
            System.out.println(cls3.hashCode());
            System.out.println(cls4.hashCode());
    
            //Other ways
            //5. Get Class objects from basic data types
            Class<Integer> integerClass = int.class;
            Class<Character> characterClass = char.class;
            System.out.println(integerClass);//The bottom layer of output int has automatic packing and unpacking processes
    
            //6. The package Class corresponding to the basic data TYPE can be passed TYPE gets the Class object
            Class<Double> type = Double.TYPE;
            System.out.println(type);//Output double
            
            Class<Integer> type1 = Integer.TYPE;
    
            //The hashCode output below is the same
            System.out.println(integerClass.hashCode());
            System.out.println(type1.hashCode());
        }
    }
    
  4. Which types have Class objects

    (1) External class, member internal class, static internal class, local internal class, anonymous internal class

    (2)interface: Interface

    (3) Array

    (4) Enumeration

    (5)annotation: Annotation

    (6) Basic data type

    (7)void

    (8)Class itself

Class loading

  1. Class loading: reflection mechanism is the key to realize dynamic language in java, that is to realize dynamic class loading through reflection

    (1) Static loading: load relevant classes during compilation. If not, an error will be reported, which is too dependent

    (2) Dynamic loading: load the required class at runtime. If the class is not used at runtime, no error will be reported, reducing the dependency

  2. Class loading time:

    (1) When creating an object (new) (static load)

    (2) When subclasses are loaded (static loading)

    (3) When calling a static member in a class (static load)

    (4) By reflection (dynamic loading)

  3. Class loading phase:

    (1) Loading:

    At this stage, the JVM mainly converts the bytecode from different data sources (possibly class files, jar packages, or even the network) into binary byte streams, loads them into memory, and generates a Java. Java representing this class Lang.class object

    (2) Linking phase:

    1) Verification: the purpose is to ensure that the information contained in the byte stream of the Class file meets the requirements of the current virtual machine and will not endanger the safety of the virtual machine itself; Including file format verification (whether it starts with magic number oxcafebabe), metadata verification, bytecode verification and symbol reference verification; Consider using the - Xverify:none parameter to turn off most of the Class verification measures and shorten the loading time of virtual machine classes

    2) Preparation: at this stage, the JVM will allocate memory and initialize static variables (not those modified by static final) (corresponding to the default initial values of data types, such as 0, null, false, etc.), and the memory used by these variables will be matched in the method area

    3) Resolution: the process by which a virtual machine replaces a symbolic reference in a constant pool with a direct reference

    (3) Initialization: the Java program code defined in the class will not be executed until the initialization stage. This stage is the process of executing the < clinit > () method< Clinit > () method is that the compiler automatically collects the assignment actions of all static variables in the class and the statements in the static code block according to the order in which the statements appear in the source file, and combines them; Virtual opportunity ensures that the < clinit > () method of a class is locked and synchronized correctly in a multithreaded environment. If multiple threads initialize a class at the same time, only one thread will execute the < clinit > () method of this class, and other threads need to block and wait until the active thread finishes executing the < clinit > () method

Reflection related operation

  1. Get class structure information through reflection

    public class ReflectionUtils {
        @Test
        //The first group is Java Lang. class class
        public void api_01() throws ClassNotFoundException {
            Class<?> personCls = Class.forName("reflection.Person");
            //1. Get the full class name
            System.out.println(personCls.getName());//reflection.Person
            //2. Get the simple class name
            System.out.println(personCls.getSimpleName());//Person
            //3. Get the attributes of all public modifications, including the attributes of this class and its parent class
            Field[] fields = personCls.getFields();
            for (Field field :fields) {
                System.out.println(field);
            }
            //4. Get all attributes in this class
            Field[] declaredFields = personCls.getDeclaredFields();
            for (Field field :declaredFields) {
                System.out.println(field.getName());
            }
            //5. Get all public modified methods, including the methods of this class and its parent class
            Method[] methods = personCls.getMethods();
            for (Method method :methods) {
                System.out.println(method.getName());
            }
            //6. get all methods in this class
            Method[] declaredMethods = personCls.getDeclaredMethods();
            for (Method method :declaredMethods) {
                System.out.println(method.getName());
            }
            //7. Get constructors of all public modifications. For this class, excluding the parent class
            Constructor<?>[] constructors = personCls.getConstructors();
            for (Constructor constructor :constructors) {
                System.out.println(constructor.getName());
            }
            //8. Get all constructors of this class
            Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
            for (Constructor constructor :declaredConstructors) {
                System.out.println(constructor.getName());
            }
            //9. Return Package information in the form of Package
            System.out.println(personCls.getPackage());
            //10. Return parent Class information in the form of Class
            System.out.println(personCls.getSuperclass());
            //11. Return interface information in the form of Class []
            Class<?>[] interfaces = personCls.getInterfaces();
            for (Class aClass :interfaces) {
                System.out.println(aClass.getName());
            }
            //12. Return Annotation information in the form of Annotation []
            Annotation[] annotations = personCls.getAnnotations();
            for (Annotation annotation :annotations) {
                System.out.println(annotation);
            }
        }
    
        @Test 
        public void api_02() throws ClassNotFoundException {
            Class<?> personCls = Class.forName("reflection.Person");
            //The second group is Java lang.reflect. Field class
            //Get all properties in this class
            Field[] declaredFields = personCls.getDeclaredFields();
            for (Field field :declaredFields) {
                //getName returns the property name
                //getModifiers returns modifiers as int
                //The default modifier is 0, public is 1, private is 2, protected is 4, static is 8 and final is 16
                //getType returns the type as Class
                System.out.println(field.getName() +
                " The modifier value of the property" + field.getModifiers()
                +" The type of the property"+field.getType());
            }
    
            //The third group is Java lang.reflect. Method class
            //Get all methods in this class
            Method[] declaredMethods = personCls.getDeclaredMethods();
            for (Method method :declaredMethods) {
                //getName returns the property name
                //getModifiers returns modifiers as int
                //The default modifier is 0, public is 1, private is 2, protected is 4, static is 8 and final is 16
                //getReturnType returns the type as Class
                System.out.println(method.getName() + "This method modifier" + method.getModifiers()
                +"The type of the method"+method.getReturnType());
    
                //getParameterTypes gets the current method parameters in the form of Class []
                Class<?>[] parameterTypes = method.getParameterTypes();
                for (Class<?> parameterType : parameterTypes) {
                    System.out.println(parameterType);
                }
            }
    
            //The fourth group is Java lang.reflect. Constructor class
            //getName returns the property name
            //getModifiers returns modifiers as int
            Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
            for (Constructor constructor :declaredConstructors) {
                System.out.println(constructor.getName());
    
                //getParameterTypes gets the current method parameters in the form of Class []
                Class[] parameterTypes = constructor.getParameterTypes();
                for (Class parameterType : parameterTypes) {
                    System.out.println("Constructor parameters" + parameterType);
                }
            }
        }
    }
    
    class A{
        public String hobby;
    
        public A() { }
    
        public void hi(){ }
    }
    
    interface IA{}
    interface IB{}
    
    @Deprecated
    class Person extends A implements IA ,IB{
        public String name;
        protected int age;
        String job;
        private double sal;
    
        public Person(){ }
        
        public Person(String s){ }
    
        private Person(String s,int i){ }
    
        public void m1(String name,int age){ }
        
        protected void m2(){ }
        
        void m3(){ }
        
        private void m4(){ }
    }
    
  2. Create objects by reflection

    Method 1: call the public modified parameterless constructor in the class

    Method 2: call the specified constructor in the class

    Class related methods:

    newInstance: call the parameterless constructor in the class to get the object of the corresponding class

    getConstructor(Class... clazz): get the corresponding public constructor object according to the parameter list

    Getdeclaredconstructor (class... clazz): get all corresponding constructor objects according to the parameter list

    Constructor class related methods:

    setAccessible: Blasting

    newInstance(Object... obj): call constructor

    /**
     * Create object instances through reflection mechanism
     */
    
    public class ReflectionCreateInstance {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
            //String classPath = "reflection.User";
            //1. Get the Class object of User Class first
            Class<?> userClass = Class.forName("reflection.User");
            //2. Create an instance through the public parameterless constructor
            Object o1 = userClass.newInstance();
            System.out.println(o1);
            //3. Create an instance through the public parameterized constructor
            Constructor<?> constructor = userClass.getConstructor(String.class);
            Object o2 = constructor.newInstance("tom");
            System.out.println(o2);
            //4. Create an instance through a non-public parameterized constructor
            Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
            declaredConstructor.setAccessible(true);//Blasting, using reflection, you can access the private constructor
            Object o3 = declaredConstructor.newInstance(20, "mike");
            System.out.println(o3);
        }
    }
    
    class User {
        private int age = 10;
        private String name = "jack";
    
        public User() {
        }
    
        public User(String name) {
            this.name = name;
        }
    
        private User(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
  3. Accessing members in a class through reflection

    /**
     * Accessing members in a class through reflection 
     */
    
    public class ReflectAccessProperty {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
            //1. Get the Class object corresponding to the Student Class
            Class<?> stuClass = Class.forName("reflection.Student");
            //2. Create object
            Object o = stuClass.newInstance();
            //3. Use reflection to get the age attribute object
            Field age = stuClass.getField("age");
            age.set(o,88);//Through reflection operation
            System.out.println(o);
            System.out.println(age.get(o));
            //4. Operation name attribute
            Field name = stuClass.getDeclaredField("name");
            name.setAccessible(true);
            name.set(o,"tom");
            //Or name set(null,"tom");   Because name is static
            System.out.println(name.get(o));
        }
    }
    
    class Student{
        public int age;
        private static String name;
    
        public Student() {
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "age=" + age + " name=" + name+
                    '}';
        }
    }
    
  4. Accessing methods in a class through reflection

    /**
     * Accessing methods in a class through reflection
     */
    
    public class ReflectAccessMethod {
        public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
            //1. Get the Class object corresponding to the Boss Class
            Class<?> bossCls = Class.forName("reflection.Boss");
            //2. Create object
            Object o = bossCls.newInstance();
            //3. Call public method
            Method hi = bossCls.getMethod("hi", String.class);
            //Method hi = bossCls.getDeclaredMethod("hi",String.class); it's fine too
            //4. Call
            hi.invoke(o, "jack");
    
            //Call private method
            Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
            say.setAccessible(true);
            System.out.println(say.invoke(o, 5, "tom", 'A'));
            //Similarly, because the say method is static, o can also be changed to null
            
            //be careful!!! In reflection, if the method has a return value, it returns Object uniformly
        }
    }
    
    class Boss {
        public int age;
        private static String name;
    
        public Boss() {
        }
    
        private static String say(int n, String s, char c) {
            return n + " " + s + " " + c;
        }
    
        public void hi(String s) {
            System.out.println("hi " + s);
        }
    }
    

Tags: Java

Posted by ndorfnz on Mon, 18 Apr 2022 09:09:33 +0930