Reflection and its API

Keywords: Java

1, The concept of reflection

1. What is reflection? Why use reflection?
When we write code before, we first write classes, then create objects with classes, and call members such as methods through class names or object names.
    ==> The name and members of this class should be determined during compilation.

For example:

  public class Student{
        private int id;
        private String name;

        public Student(){
        }
        public Student(int id, String name){
            this.id = id;
            this.name = name;
        }
        public void setId(int id){
            this.id = id;
        }
        public int getId(){
             return id;
        }
        //...
    }

    public class TestStudent{
        public static void main(String[] args){
            Student stu1  = new Student();
            Student stu2  = new Student(1,"Zhang San");
            System.out.println(stu1.getId());
        }
    }

Now, in the development process, we will encounter such situations: during compilation, the type is unknown or does not exist during compilation,
However, we need to complete the new object, calling method and other codes first. The type, etc. can only be determined at runtime.


Class -- > class information
Class object -- > class information

The Class object of the Class is the mirror image of the Class. This process is compared to reflection.

2. Source of reflection: object of Class type

public class TestReflect {
    public static void main(String[] args) {
        //Write the code to create the object first
        Properties pro  = new Properties();//Map series, with key,value, key and value of String type
        try {
            pro.load(TestReflect.class.getClassLoader().getResourceAsStream("info.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            Class<?> clazz = Class.forName(pro.getProperty("className"));//"className" is a key in the info.properties file
            //pro.getProperty("className") is obtained, but the key in the info.properties file is the value value of className, that is, the value on the right of className =
        
            //new object
            Object obj = clazz.newInstance();
            System.out.println(obj);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }
}

3. Where are the properties files?
(1) Put it in the root directory of src

(2) Put it in a bag

(3) Outside src, under the root directory of the module

public class TestLoaderProperties {
    public static void main(String[] args)throws Exception {
        Properties pro = new Properties();
        ClassLoader classLoader = TestLoaderProperties.class.getClassLoader();
        pro.load(classLoader.getResourceAsStream("info.properties"));//src root directory
        System.out.println(pro);

        System.out.println("---------------------------");
        Properties pro2 = new Properties();
        ClassLoader classLoader2 = TestLoaderProperties.class.getClassLoader();
        pro2.load(classLoader2.getResourceAsStream("com/atguigu/reflect/pkg.properties"));//com.atguigu.reflect package
        System.out.println(pro2);

        System.out.println("----------------------");
        Properties pro3 = new Properties();
        //If it is run in the main method, the module name must be added. The relative path of main is relative to project
        pro3.load(new FileInputStream("day0831_teacher_code/out.properties"));//src, under the module root directory
        System.out.println(pro3);
    }

    @Test
    public void test() throws Exception {
        //The relative path of JUnit is relative to the module
        Properties pro3 = new Properties();
        pro3.load(new FileInputStream("out.properties"));//src, under the module root directory
        System.out.println(pro3);
    }
}

2, Class loading process

3. How did the Class object come from?
When a Java program runs, it will first "load" the class information such as the. Class file of the required class into memory,
After each Java type is "loaded", it will be stored and represented by a Class object.

4. Class loading is divided into three stages: (understand)
(1) load: first read the data of the. class file into memory
(2) Connect (link)
A: Test legitimacy
    For example, check the format of bytecode file, including version, etc
    The of bytecode file must be in cafebabe
B: Prepare the corresponding memory
    Prepare the new Class object,
    Class's static variable data storage memory (method area)   This is the default value and has not been initialized
    Class, which will be initialized directly at this time.   public static final int MAX_VALUE = 100;
C: Analysis
    Replace the symbol reference in bytecode file with address reference
    For example: Student class
        public class Student {
            private int id;
            private String name;
        . . . .
    }
    For example, string and int are symbolic references,
    String and int are also Java data types and have their Class objects in memory. At this time, replace string and int with the first addresses of the Class objects of these two types in memory.

    Why replace it with an address reference?
    In this way, when running, you don't need to find it now, and you can get the corresponding information directly according to the address.

    After the first two steps, the Class object is, but the static variable of this Class has not been initialized.
(3) Initialization
    Run the < clinit > method of this class

    After the first three steps, the Class object is and the static variable is initialized.


5. Who completes the loading of classes?
Class loading is done by the class loader ClassLoader. The bottom layer has a special thread to load the class.

Class loaders are divided into four types:
(1) Boot class loader: responsible for the classes in the core class library and the classes under rt.jar
    Note: the boot class loader is written in C language, so its object cannot be obtained at the Java level
(2) Extclassloader: it is responsible for jar in ext extension directory under lib directory under JRE
(3) Application class loader: responsible for the classes written by programmers themselves

(4) Custom class loader: it is also used to load classes written by programmers, and load some special classes and special directories
    For example, if the bytecode needs to be encrypted, it must be decrypted with the corresponding class loader before it can be loaded normally.
      For example, bytecode files are not placed under the normal classpath. For example, the classpath of IDEA is out.
            The classpath of tomcat server is special, so it can't be loaded with ordinary classloader, so it needs to be loaded with custom classloader. tomcat writes custom classloader.

6. How do I get the class loader?
  The Class object of the Class can call the getClassLoader() method to get the Class loader object.


7. Class loaded collaboration mode: parent delegation mode, which is designed for security.
  Parents: parents

Parents:
The application class loader treats the extension class loader as a parent, but not an inheritance. There is a parent member variable in the application class loader to record the extension class loader.
The extension class loader treats the boot class loader as a parent, but not an inheritance. There is a parent member variable in the extension class loader to record the boot class loader.

Process Description:
(1) When our application Class loader receives the loading task, first check whether this Class has been loaded in memory. If it has been loaded, it will not be loaded again, and the Class object will be returned directly.
If it has not been loaded, first hand over the task to the "parents", that is, the extension class loader.
For example, the application class loader receives the task of loading "java.lang.String". If the class has not been loaded, the task is sent to the extension class loader
For example, the application class loader receives the task of loading "java.lang.Atguigu". If the class has not been loaded, the task is sent to the extension class loader

(2) After receiving the loading task, the extension Class loader also checks whether this Class has been loaded in memory. If it has been loaded, it will not be loaded again and will directly return the Class object.
If it has not been loaded, the task is handed over to the "parents", that is, the boot class loader.
For example, the extension class loader receives the task of loading "java.lang.String". If this class has not been loaded, the task is sent to the boot class loader
For example, the extension class loader receives the task of loading "java.lang.Atguigu". If this class has not been loaded, give the task to the boot class loader

(3) After receiving the loading task, the boot Class loader also checks whether this Class has been loaded in memory. If it has been loaded, it will not be loaded again and will directly return the Class object.
If it has not been loaded, try to search this class in the directory it is responsible for,
For example, the boot Class loader receives the task of loading "java.lang.String", loads it in the directory it is responsible for, finds it in rt.jar, and returns the Class object if it is found.
For example, the boot Class loader receives the task of loading "java.lang.Atguigu", loads it in the directory it is responsible for, finds it in rt.jar, and returns the Class object if it is found.
    If not, pass the task back to the extension class loader

(4) When the extension Class loader receives the task of guiding the Class to return again, it will search the Class in the directory it is responsible for. If it finds it, it will return the Class object.
    If not, send the task back to the application class loader

(5) The application Class loader is connected to the extension Class loader again   For the returned task, it will search for this Class in the directory it is responsible for. If it is found, it will return the Class object.
    If it is not found, an error ClassNotFoundException is reported


Summary:
    The class loading process is completed by the class loader. There are four (usually three) working modes. The working mode is the two parent delegation mode for security.
    The result of Class loading is to get the Class object of a Class.

public class TestClassLoad {
    public static void main(String[] args) {
        System.out.println(MyClass.MAX_VALUE);
        System.out.println(MyClass.a);

        System.out.println("-------------------------------");
        //String.class gets the class object of string class
        ClassLoader classLoader = String.class.getClassLoader();
        System.out.println("load String Class loader:" + classLoader);//null

        //TestClassLoad.class gets the Class object of TestClassLoad Class
        ClassLoader loader = TestClassLoad.class.getClassLoader();
        System.out.println("Programmer custom class TestClassLoad Class loader object for class:" + loader);//sun.misc.Launcher$AppClassLoader@18b4aac2
        ClassLoader parent = loader.getParent();
        System.out.println("app Class loader parent: " + parent);

        System.out.println("-------------------------------");
        try {
            //Class.forName("com.atguigu.loader.TestLoader") gets the class object of TestLoader
            Class clazz = Class.forName("com.atguigu.loader.TestLoader");
            System.out.println("stay JRE/lib/ext Under directory TestLoader Class loader for class:" + clazz.getClassLoader()); //sun.misc.Launcher$ExtClassLoader@45ee12a7
            ClassLoader ext = clazz.getClassLoader();
            System.out.println("ext Extension class loader parent: "+ ext.getParent());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try {
            //Class.forName("java.lang.Atguigu") gets the class object of Atguigu
            Class clazz = Class.forName("java.lang.Atguigu");//ClassNotFoundException:
            System.out.println("Atguigu Class Class Object:" + clazz);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class MyClass{
    public static final int MAX_VALUE = 100; //Direct assignment in the preparation stage of class loading
    public static int a = 100;//The initialization phase of class loading completes the assignment
    static{
        System.out.println("Static code block");//Class initialization execution
    }
}

3, Reflection source Class
1. Why is there a Class type?
Java data types, especially reference data types, such as classes,
They have many common features:
    Take class as an example
    There are class names, modifiers, parent classes, parent interfaces, member variables, member methods, constructors
    You can create objects, call methods and other operations
Java class is an abstract description of a class of things with the same characteristics.

Class is an abstract description of Java data types.
Class is an object that represents a specific Java data type.

java.lang.String type. There is a Class object in JAVA memory to represent it, and this object is unique.
java.lang.Integer type. There is also a Class object in JAVA memory to represent it, and this object is also unique.
    If two variables are of the same type, they use the same Class object.

2. Which Java types have Class objects?
An instance of the Class represents classes and interfaces in a running Java application.
Enumeration is a kind and annotation is an interface.
Each array belongs to a Class mapped as a Class object, which is shared by all arrays with the same element type and dimension.
The basic Java types (boolean, byte, char, short, int, long, float, and double) and the keyword void are also represented as Class objects.

Conclusion: all Java data types have Class objects.

3. How to get a Class object?
Class has no public constructor. Class objects are automatically constructed by the Java virtual machine when loading classes and by calling the defineClass method in the class loader.
There are four ways to obtain: (must master)
(1) Type name.class
    Applies to types known and existing by the compiler
(2) Object. getClass()
    This method is used in the Object class to get the runtime type of the Object
    Get the runtime type of the object when applicable to polymorphic references
(3) Class.forName("full name of type")
    Applies to types that are unknown or do not exist during compilation
(4) Class loader object. loadClass("full name of type")

public class TestClass {
    @Test
    public void test06(){
        //TestClass.class get the Class object of TestClass
        //TestClass.class.getClassLoader() gets the classloader object that loads TestClass
        ClassLoader classLoader = TestClass.class.getClassLoader();

        try {
            //Use this classloader object to load other classes
            Class<?> c1 = classLoader.loadClass("com.atguigu.bean.Teacher");
            Class c2 = Teacher.class;
            System.out.println(c1 == c2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    @Test
    public void test05(){
        try {
            Class<?> c1 = Class.forName("java.lang.String");
            Object obj = "hello";//Polymorphic reference
            Class<?> c2 = obj.getClass();
            Class<?> c3 = String.class;

            System.out.println(c1 == c2);
            System.out.println(c1 == c3);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
    @Test
    public void test04(){
        int[] arr1 = {1,2,3,4,5};
        int[] arr2 = new int[10];

        Class c1 = arr1.getClass();
        Class c2 = arr2.getClass();
        System.out.println(c1 == c2);//true only looks at the type and dimension of the element, not the value of the element and the length of the array
    }

    @Test
    public void test03(){
        Object obj = "hello";//Polymorphic reference
        Class<?> c1 = obj.getClass();  //Get the runtime type of obj, which is a Class object of String type
        Class stringClass = String.class;

        System.out.println(c1 == stringClass);//true
    }

    @Test
    public void test02(){
        Class c1 = "hello".getClass();//Class object representing the runtime type String of the object "hello"
        Class stringClass = String.class;  //The result is a Class object representing a String type

        //If the address of the comparison object is the same object, true will be returned
        System.out.println(c1 == stringClass);//true. Both of them are java.lang.String. In memory, there is only one Class object to represent the String type
    }

    //Demonstrate that all Java data types need their own Class objects
    @Test
    public void test01(){
        //class
        Class stringClass = String.class;
        Class integerClass = Integer.class;

        //Basic data type and void
        Class intClass = int.class;
        Class voidClass = void.class;

        System.out.println(stringClass == integerClass) ;//false
        System.out.println(intClass == integerClass) ;//false

        Class intArrayClass = int[].class;
        Class intArray2Class = int[][].class;
        System.out.println(intArrayClass == intArray2Class);//false

        Class stringArrayClass =  String[].class;
        System.out.println(intArrayClass == stringArrayClass);//false
        System.out.println(stringClass == stringArrayClass);//false

        //Interface
        Class  s1 =  Serializable.class;
        //annotation
        Class  o1 =   Override.class;
        //enumeration
        Class m1 = Month.class;

    }
}

4, Application of reflection
1. Get class information
When you get the Class object of a Class, you can see through the Class.

public class TestClassInfo {
    public static void main(String[] args)throws Exception {
        Class<?> clazz = Class.forName("java.lang.String");//Here, take String as an example. It can be any other type

        //Get Class information through Class object
        //(1) Get package
        Package pkg = clazz.getPackage();
        System.out.println("pkg = " + pkg);

        //(2) Get type name
        String name = clazz.getName();
        System.out.println("name = " + name); //Full name = package + class name
        
        //(3) Modifier
        int modifiers = clazz.getModifiers();
        System.out.println("modifiers = " + modifiers);//17
        /*
        java.lang.reflect The Modifier under the package describes all JAVA modifiers
                                                      Hexadecimal decimal binary
        public static final int PUBLIC           = 0x00000001;      1           1
        public static final int PRIVATE          = 0x00000002;      2           10
        public static final int PROTECTED        = 0x00000004;      4           100
        public static final int STATIC           = 0x00000008;      8           1000
        public static final int FINAL            = 0x00000010;      16          10000

        Each modifier is to the nth power of 2. Their binary characteristic is that one bit is 1 and the others are 0

        public:     00000000 00000000 00000000 00000001
        final :     00000000 00000000 00000000 00010000
        |Bitwise OR: 00000000 00000000 00010001 17

        17 Binary of: 00000000 00000000 000100010001
        &
        public:    00000000 00000000 00000000 00000001
                   00000000 00000000 00000000 00000001 Non 0, indicating public

         17 Binary of: 00000000 00000000 000100010001
        &
        private:    00000000 00000000 00000000 00000010
                    00000000 00000000 00000000 00000000 0,It means there is no private
         */
        System.out.println(Modifier.toString(modifiers));//public final

        //(4) Parent class
        Class<?> superclass = clazz.getSuperclass();
        System.out.println("Parent class:" + superclass);

        //(5) Parent interfaces
        System.out.println("Parent interfaces are:");
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface);
        }

        //(6) Member variables
        /*
        Field getField(String name): Get a public property according to the property name
        Field getDeclaredField(String name): Gets a declared property based on the property name
        Field[] getFields() : Get all public properties
        Field[] getDeclaredFields() : Get all declared properties
         */
        System.out.println("Get all properties:");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        //Get one of the properties
        Field valueField = clazz.getDeclaredField("value");
        int mod = valueField.getModifiers();
        System.out.println("mod = " + mod);//18
        System.out.println("value Modifier for property:" + Modifier.toString(mod));//private final
        System.out.println("value Name of:" + valueField.getName());
        System.out.println("value Data type:" + valueField.getType());//[C] represents one-dimensional array, and C represents char type

        //(7) Get all constructors
        /*
        Constructor<T> getConstructor(Class<?>... parameterTypes): Get a public constructor
        Constructor<?>[] getConstructors(): All public constructors
        Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  : Gets the constructor of a declaration
        Constructor<?>[] getDeclaredConstructors()  : Gets the constructor for all declarations of a
         */
        System.out.println("All constructors:");
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        //Get a constructor
        //Constructor<T> getDeclaredConstructor(Class<?>...  Parametertypes): gets the constructor of a declaration
        //(Class<?>...  Parametertypes), because the number of formal parameters of the constructor is 0~n
        //Constructors can be overloaded and distinguished by the formal parameter list of constructors. Therefore, to obtain a constructor, you need to specify the type of the formal parameter list of the piece constructor
        //public java.lang.String(byte[])
       Constructor c = clazz.getDeclaredConstructor(byte[].class);//Get the constructor of String class whose formal parameter is byte [] type
        System.out.println("Formal parameter is byte[]Constructor of type:" + c);

        //(8) All methods
        /*
        Method getDeclaredMethod(String name, Class<?>... parameterTypes): Get a declared method, and determine a method by specifying the name of the method and the formal parameter list of the method
        Method[] getDeclaredMethods(): Gets all declared methods
        Method getMethod(String name, Class<?>... parameterTypes): Get a public method, and determine a method by specifying the name of the method and the formal parameter list of the method
        Method[] getMethods(): Get all public methods
         */
        System.out.println("All the ways:");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
    }
}

2. Create objects of any type at run time
Any type: excluding basic data type, void, abstract class, interface, etc
Any type: refers to the type of object that can be created.

Briefly describe:
    Later, we will write Java EE Projects.
    ( 1) The server-side code written later runs in the web server (for example, tomcat),
    There are many classes on the server side, some of which are created by the web server. For example: servlet class (representing jsp page)
    ( 2) The later projects will use spring,mybatis and other frameworks, and our classes will also be handed over to the spring framework to help us manage,
    Our class objects are created by the spring framework.

    The web server, spring,mybatis and other framework codes have been written, and our class was written later.
    The new object code is written in advance in the web server, spring,mybatis and other frameworks. We later passed the specific new object class
    The xx.xml file tells the server or framework, and then they can read the configuration file to get the "Class name" and the corresponding Class object,
    Then the new object.


Method 1: directly use the newInstance() method of Class class to create objects
There is a frequently used method in Class:
    T newInstance(): create a new instance of the Class represented by this Class object.
        If this Class object represents a String type, newInstance() creates a String object
        If this Class object represents the Student type, newInstance() creates the Student object
        If this Class object represents the Date type, newInstance() creates the Date object

    To create an instance object in this way, this type must have a public parameterless structure, otherwise it will report illegalaccessexception and instantiationexception.
            Report IllegalAccessException: there is a problem with the permission modifier of the constructor
            InstantiationException: no parameterless construct
Method 2: first obtain the constructor object of this class, and then create the object through the newInstance method of the constructor object
    In this way, the constructor can be parameterless, parameterless, or any permission modification.

public class TestNewInstance {
    @Test
    public void test3() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        /*
        Suppose the configuration file of the framework is called info.properties
        There are various configuration information such as key=value. One key is className, and its value is the type name of the object you want to create
        For example: className=java.util.Date
         */
        //(1) First, read the configuration file
        //If the info.properties file is in the root directory of src
        //src is a source code file. Everything in it will be compiled by the compiler into the class path (out directory), that is, the configuration file under src will be together with the. Class file
        //The. Class file can be loaded through "application class loader", and the configuration file under src can also be loaded through "application class loader"
        Properties properties = new Properties();
        /*
        TestNewInstance Class is a class written by the programmer himself, so it is loaded by the "application class loader"
        TestNewInstance.class Get its Class object
        TestNewInstance.class.getClassLoader()Get the class loader object, that is, the "application class loader" object
         */
        ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object
        properties.load(classLoader.getResourceAsStream("info.properties"));

        //After the above code, the data in "info.properties" is stored in the map of properties and stored in the form of (key,value)
        //(2) Step 2: get the value according to the key to get the name of the class to be loaded
        String className = properties.getProperty("className");

        //(3) Step 3: get its Class object in memory
        Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException

        //(4) Get a constructor object
        //For example, I want to get the public Teacher(String name,double salary) constructor
        Constructor c = clazz.getDeclaredConstructor(String.class,double.class);//String.class represents that the type of formal parameter is string type

        //(5) Object call through constructor
        //java.lang.reflect.Constructor class T newInstance(Object... initargs)
        //The parameters of newInstance(Object... initargs) are finally the arguments passed to the constructor you call
        //c.newInstance("Zhang San", 15000); "Zhang San" here is equivalent to your new Teacher("Zhang San", 15000)

        //You can do this if the called constructor cannot create an object because of the visibility of the permission modifier
        c.setAccessible(true);//Permission modifier check skipped

        Object obj = c.newInstance("Zhang San",15000);

        System.out.println(obj);
    }

    @Test
    public void test2() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        /*
        Suppose the configuration file of the framework is called info.properties
        There are various configuration information such as key=value. One key is className, and its value is the type name of the object you want to create
        For example: className=java.util.Date
         */
        //(1) First, read the configuration file
        //If the info.properties file is in the root directory of src
        //src is a source code file. Everything in it will be compiled by the compiler into the class path (out directory), that is, the configuration file under src will be together with the. Class file
        //The. Class file can be loaded through "application class loader", and the configuration file under src can also be loaded through "application class loader"
        Properties properties = new Properties();
        /*
        TestNewInstance Class is a class written by the programmer himself, so it is loaded by the "application class loader"
        TestNewInstance.class Get its Class object
        TestNewInstance.class.getClassLoader()Get the class loader object, that is, the "application class loader" object
         */
        ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object
        properties.load(classLoader.getResourceAsStream("info.properties"));

        //After the above code, the data in "info.properties" is stored in the map of properties and stored in the form of (key,value)
        //(2) Step 2: get the value according to the key to get the name of the class to be loaded
        String className = properties.getProperty("className");

        //(3) Step 3: get its Class object in memory
        Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException

        //(4) Get a constructor object
        //For example, I want to get the public Teacher(String name) constructor of the Teacher class
        Constructor c = clazz.getDeclaredConstructor(String.class);//String.class represents that the type of formal parameter is string type

        //(5) Object call through constructor
        //java.lang.reflect.Constructor class T newInstance(Object... initargs)
        //The parameters of newInstance(Object... initargs) are finally the arguments passed to the constructor you call
        //c.newInstance("Zhang San"); "Zhang San" here is equivalent to your new Teacher("Zhang San")
        Object obj = c.newInstance("Zhang San");

        System.out.println(obj);
    }


    @Test
    public void test() throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        /*
        Suppose the configuration file of the framework is called info.properties
        There are various configuration information such as key=value. One key is className, and its value is the type name of the object you want to create
        For example: className=java.util.Date
         */
        //(1) First, read the configuration file
        //If the info.properties file is in the root directory of src
        //src is a source code file. Everything in it will be compiled by the compiler into the class path (out directory), that is, the configuration file under src will be together with the. Class file
        //The. Class file can be loaded through "application class loader", and the configuration file under src can also be loaded through "application class loader"
        Properties properties = new Properties();
        /*
        TestNewInstance Class is a class written by the programmer himself, so it is loaded by the "application class loader"
        TestNewInstance.class Get its Class object
        TestNewInstance.class.getClassLoader()Get the class loader object, that is, the "application class loader" object
         */
        ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object
        properties.load(classLoader.getResourceAsStream("info.properties"));

        //After the above code, the data in "info.properties" is stored in the map of properties and stored in the form of (key,value)
        //(2) Step 2: get the value according to the key to get the name of the class to be loaded
        String className = properties.getProperty("className");

        //(3) Step 3: get its Class object in memory
        Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException

        //(4) Step 4: create object
//        Through the Class object of this Class, call the newInstance() method to create the object
        Object obj = clazz.newInstance();
        System.out.println(obj);

    }
}

3. The properties of any object can be accessed / manipulated at run time
Steps:
(1) Get the Class object first
(2) Get the Field object of the property you want to operate on / access
(3) If you want to access a static variable, you can access the value of the static variable by calling the set/get method of the Field object
    If you want to access a non static variable, you also need to create an object of this class, and then the set/get method of the Field object can access the value of the non static variable

public class TestAccessField {
    @Test
    public void test03() throws NoSuchFieldException, IllegalAccessException {
        String str = "hello";
        //Modify the string content of str, assuming that e is changed to a

        Class<? extends String> stringClass = str.getClass();//Get the Class object of String Class
        Field valueField = stringClass.getDeclaredField("value");//Get the private final char value [] in the String class;
        //Because the value attribute is private in the String class, you need to skip the permission modifier check
        valueField.setAccessible(true);
        Object o = valueField.get(str);//Get the value array of str string
        char[] arr = (char[]) o;//Cast to char [] type
        arr[1] = 'a';

        System.out.println(str);//hallo
    }

    @Test
    public void test02() throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        //(1) First, read the configuration file
        Properties properties = new Properties();
        ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object
        properties.load(classLoader.getResourceAsStream("info.properties"));

        //(2) Step 2: get the value according to the key to get the name of the class to be loaded
        String className = properties.getProperty("className");

        //(3) Step 3: get its Class object in memory
        Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException

        //(4) Step 4: get the Field object of the attribute to be operated
        Field companyField = clazz.getDeclaredField("company");

        //Because the company attribute is static, there is no need to create a Teacher object
        //(5) Call the set and get methods of the Field object to operate the company property
        //If the property is private, you can avoid permission modifier checking through the following operations
        companyField.setAccessible(true);
        companyField.set(null,"Shang Silicon Valley");
        Object value = companyField.get(null);
        System.out.println("value = " + value);

    }

    @Test
    public void test01() throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        //(1) First, read the configuration file
        Properties properties = new Properties();
        ClassLoader classLoader = TestNewInstance.class.getClassLoader();//Gets the application class loader object
        properties.load(classLoader.getResourceAsStream("info.properties"));

        //(2) Step 2: get the value according to the key to get the name of the class to be loaded
        String className = properties.getProperty("className");

        //(3) Step 3: get its Class object in memory
        Class clazz = Class.forName(className);//If this class is not in memory, the application class loader will try to load it. If it is not found, it will report ClassNotFoundException

        //(4) Step 4: get the Field object of the attribute to be operated
        Field nameField = clazz.getDeclaredField("name");

        //(5) Because the name attribute is non static, you need to create a Teacher object to manipulate it
        //Here, Teacher has a public parameterless structure,
        Object teacher = clazz.newInstance();
        
        //(6) Call the set and get methods of the Field object to operate on the name property
        //If the property is private, you can avoid permission modifier checking through the following operations
        nameField.setAccessible(true);
        nameField.set(teacher,"Li Si");
        Object value = nameField.get(teacher);
        System.out.println("value = " + value);
        System.out.println(teacher);
    }
}

4. Call any method at run time

Demonstrates calling various methods in the com.atguigu.test.Father class through reflection

public class TestInvokeMethod {
    @Test
    public void test4() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about
        Class clazz = Class.forName("com.atguigu.test.Father");

        //(2) Step 2: get the Method object of the Method you want to call
        // public int sum(int a, int b) is a non static method
        Method sumMethod = clazz.getDeclaredMethod("sum",int.class,int.class);

        //(3) Step 3: if it is a non static method, you need to create an object of the Father class first
        Object obj = clazz.newInstance();//Create an object of the Father class. Because clazz represents the Father class, the Father class is required to have a public parameterless structure
        Object value = sumMethod.invoke(obj, 1, 5);//Obj here means to call the fun method through the Father object obj, which is equivalent to ((Father)obj).fun();
        //If the sum method has a return value, the return value is passed back through the invoke call
        System.out.println("value = " + value);
    }

    @Test
    public void test3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about
        Class clazz = Class.forName("com.atguigu.test.Father");

        //(2) Step 2: get the Method object of the Method you want to call
        // public void fun() is a non static method
        Method funMethod = clazz.getDeclaredMethod("fun");

        //(3) Step 3: if it is a non static method, you need to create an object of the Father class first
        Object obj = clazz.newInstance();//Create an object of the Father class. Because clazz represents the Father class, the Father class is required to have a public parameterless structure
        funMethod.invoke(obj);//Obj here means to call the fun method through the Father object obj, which is equivalent to ((Father)obj).fun();


    }

    @Test
    public void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about
        Class clazz = Class.forName("com.atguigu.test.Father");

        //(2) Step 2: get the Method object of the Method you want to call
        //  public static void test(int a) is a static method
        Method testMethod = clazz.getDeclaredMethod("test",int.class); //int.class means to get the test method with a formal parameter of type int

        //(3) Step 3: if it is a static method, it can be called directly
        testMethod.invoke(null, 100);//null here means that an object of the Father class is not required
                                                //The 100 here is the 100 assigned to the formal parameter of the test method

    }

    @Test
    public void test1() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //(1) The first step is to obtain the Class object of the Father Class through one of the four methods we talked about
        Class clazz = Class.forName("com.atguigu.test.Father");

        //(2) Step 2: get the Method object of the Method you want to call
        // public static void test() is a static method
        Method testMethod = clazz.getDeclaredMethod("test");

        //(3) Step 3: if it is a static method, it can be called directly
        testMethod.invoke(null);//null here means that an object of the Father class is not required


    }
}

5. Gets information about the generic parent class

Demonstrates how to obtain the generic information of the generic parent class Father of the subclass Sub. when the subclass Sub inherits the parent class Father, it specifies the generic information Father < string, integer >

public class TestGenericFather {
    public static void main(String[] args)throws Exception {
        //(1) The first step is to obtain the Class object of the Sub Class
        Class clazz = Class.forName("com.atguigu.reflect.kuo.Sub");

        //(2) Step 2: get the Type object of the generic parent class
        Class superclass = clazz.getSuperclass();
        System.out.println(superclass);//Generic information is not available in this way

        Type genericSuperclass = clazz.getGenericSuperclass();
        /*
        JDK1.5 Generics are introduced. Originally, all types are represented by Class objects. However, with generics,
        Some types cannot be represented by Class objects, such as ArrayList < string >, ArrayList <? > Wait,
        JDK Types such as Type interface are added to represent various types with generics.

        Type It is a common high-level interface of all types in the Java programming language. They include primitive types, parameterized types, array types, type variables, and primitive types.
        Type The implementation classes include Class and some sub interfaces: genericarraytype, parameterizedtype, TypeVariable < d >, wildcardtype
            GenericArrayType: Represents T [] generic array
            ParameterizedType: Represents the ArrayList < string > parameterized type
            TypeVariable<D>: Represents generic types such as T
            WildcardType: Represents the generic type ArrayList with wildcards <? >, Arraylist<?  Extensions upper limit >, ArrayList <? Super lower limit >

        Father<String,Integer>Is a ParameterizedType parameterized type
         */
        ParameterizedType pt = (ParameterizedType) genericSuperclass;//The downward transformation is to call the getActualTypeArguments method of the sub interface
        Type[] actualTypeArguments = pt.getActualTypeArguments();//Get the specific type parameter of the generic, that is, the specific type in < >
        for (Type actualTypeArgument : actualTypeArguments) {
            System.out.println(actualTypeArgument);
        }

        System.out.println("-------------------------");
        Type[] genericInterfaces = clazz.getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            if(genericInterface instanceof ParameterizedType){
                ParameterizedType p = (ParameterizedType) genericInterface;
                Type[] arr = p.getActualTypeArguments();
                System.out.println(Arrays.toString(arr));
            }
        }
    }
}

class Father<T,U>{

}
class Sub extends Father<ArrayList<String>,Integer>   implements Comparable<Sub>, Serializable {

    @Override
    public int compareTo(Sub o) {
        return 0;
    }
}

6. Get information about inner and outer classes

Demonstrates how to get the inner class information of the Outer class

Class:
    Class<?>[] Getclasses (): get all public internal classes and internal interfaces
    Class<?>[] getDeclaredClasses()  : Get all declared inner classes and inner interfaces

      Class<?> Getenclosingclass(): get the information of external class or external interface
 

public class TestInnerOuter {
    public static void main(String[] args) {
        //Step 1: get the Class object of Outer Class
        Class clazz = Outer.class;

        //Step 2: get its internal class information
        Class[] arr = clazz.getDeclaredClasses();
        for (Class c : arr) {
            System.out.println(c);
        }

        System.out.println("-----------------------");
        //Get all inner classes of HashMap
        Class hashMapClass = HashMap.class;
        //Get the inner class of HashMap
        Class[] declaredClasses = hashMapClass.getDeclaredClasses();
        for (Class declaredClass : declaredClasses) {
            System.out.println(declaredClass);
        }

        System.out.println("------------------------");
        //Demonstrates how to get the external class information of the Inner class
        //Step 1: get the Class object of Inner
        Class innerClass = Outer.Inner.class;
        //Step 2: get the new external class
        Class enclosingClass = innerClass.getEnclosingClass();
        System.out.println(enclosingClass);


        System.out.println("------------------------");
        List<Integer> list = Arrays.asList(1, 2, 3, 4);
        Class<? extends List> listClass = list.getClass();
        Class<?> c = listClass.getEnclosingClass();
        System.out.println("listClass=" + listClass);
        System.out.println("listClass External class for=" + c);
    }
}

class Outer{
    class Inner{

    }
    static class NeiClass{

    }
}

7. Reflection operation array

Under the java.lang.reflect package, the Array class provides methods for dynamically creating and accessing Java arrays.
    static Object newInstance(Class<?> componentType, int length)
        Class<?> Componenttype: the type of array element
        int length: the length of the array

public class TestArray {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>(String.class,5);
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("mysql");
        list.add("atguigu");
        list.add("chai");

        String str = list.get(1);
        System.out.println(str);
    }

    @Test
    public void test(){
        Object arr = Array.newInstance(int.class, 5);
        Array.set(arr,0,10);
        Array.set(arr,1,20);

        System.out.println(Array.get(arr,0));
        System.out.println(Array.get(arr,1));
        System.out.println(Array.get(arr,2));
    }
}
import java.lang.reflect.Array;
import java.util.Arrays;

public class MyArrayList<T> {
    private T[] arr;
    private int total;

    public MyArrayList(Class tClassType,int length){
        arr = (T[]) Array.newInstance(tClassType, 5);
    }

    public void add(T element){
        if(total>=arr.length){
            arr = Arrays.copyOf(arr, arr.length*2);
        }
        arr[total++] = element;
    }
    public T get(int index){
        return arr[index];
    }
}

8. Reflection works with custom annotations

(1) Custom annotation
Syntax format:
[modifier] @ interface annotation name{
}

Syntax format:
[modifier] @ interface annotation name{
    Abstract methods;
}

Syntax format:
[modifier] @ interface annotation name{
    Return value type method name ()   Default default return value;
}

Note: there are requirements for return value types. There are 8 basic data types, String type, Class type, annotation type, or their arrays. Other types are not allowed

(2) Use custom annotations
If the annotation used does not have an abstract method, or the abstract method has a default return value, you do not need to specify the return value for the abstract method when using the annotation
Otherwise, if the annotation used has an abstract method and the abstract method does not specify a default return value, you must specify a return value for the non abstract method in () after the annotation name.

Note: if the abstract method name is value, value = can be omitted when specifying the return value of the method when using annotations.
However, if the method name is another word or there are multiple abstract methods, it cannot be omitted   Method name=

(3) Take a look at the system annotation declaration
@Override: java.lang package

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
    // There are no abstract methods
}

@SuppressWarnings

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();  // Abstract method
}

(4) Meta annotation
The annotation added to the annotation is called meta annotation.
There are four meta annotations:
@Target: indicates where the annotation is used
    Its location is specified by the 10 constant objects of the ElementType enumeration class
@Retention: indicates the lifecycle of the annotation
    Its life cycle is specified by three constant objects of the RetentionPolicy enumeration class
        Source (source code)
        Class (bytecode)
        RUNTIME   Only annotations that live to RUNTIME can be read by reflection.
@Documented: whether the annotation can be recognized by javadoc.exe and read into the API document
@Inherited: can it be inherited by subclasses

public class TestAnnotation {
    @SuppressWarnings(value="unused")
    public static void main(String[] args) {
        int a = 1;

        //Try to get the annotation above the MyClass class
        //Step 1: get the Class object of MyClass Class first
       Class clazz =  MyClass.class;
       //Step 2: get the annotation on the class
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
            if(annotation instanceof MyAnnotation){
                MyAnnotation my = (MyAnnotation) annotation;//Transition down to call the abstract method declared in MyAnnotation
                System.out.println(my.info());
                System.out.println(my.value());
            }
        }

        System.out.println("------------------------");
        //Demonstrate that the MySub subclass inherits the MyAnnotation annotation annotation of the parent class
        Class<MySub> mySubClass = MySub.class;
        System.out.println(mySubClass.getAnnotation(MyAnnotation.class));
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Inherited  //Can be inherited by subclasses
@interface MyAnnotation{
    String value();
    String info() default "atguigu";
}


@interface OtherAnnotation{

}

@OtherAnnotation
@MyAnnotation(value="Shang Silicon Valley",info="Beijing Shangshan Silicon Valley")
class MyClass{

}

class MySub extends MyClass{

}

class Base{
    public void method(){
        System.out.println("Method of parent class");
    }
}

class Son extends Base{
    @Override //Because the Override annotation has no abstract method, you can directly use @ Override without adding (), specifying the return value of the abstract method
    public void method() {
        super.method();
    }
}

Posted by GingerRobot on Thu, 02 Sep 2021 15:46:03 -0700