What is reflection?

First of all, this reflection must not be the same as a physical reflection. But! It’s the same thing. Let’s talk a little bit about what orthomorphism is. In Java we usually create an object, we call a class constructor directly, new an object, and we have a certain class in our hand. But in fact, there are limitations: that is, we cannot write our programs dynamically according to specific situations and specific requirements. Reflection will be able to do this, however, before the code to run, we are not sure in the future will use which kind of data structure, only when the program is run to decide which one to use data classes, and reflection can dynamically in the process of program is running for class information and call class method, so that it can realize our dynamic programming. Reflection is like an object of a class that stands in front of a mirror and looks at itself in the mirror and gets all kinds of information about the class.

For example, when we run the game, we want to make a plug-in, so the design of my plug-in can not be written to death, but according to the game program specific problems specific analysis to modify the game data, at this time we have to use the principle of reflection.

  • Reflection idea: Determine and parse data class types during program execution.
  • The reflection of therole: in theCompile timeScenarios that cannot determine which data class to use, passreflectionThis can be done while the program is runningConstruct different data class instances.

There are many uses for reflection, and the common functions are as follows:

  • Gets the Class object of a Class at runtime
  • Construct an instantiation object of a class at run time
  • Gets all the information about a class at run time: variables, methods, constructors, annotations

How to use reflection

Class User:

class User { private String name; private int id; private int age; public User() { } public void setName(String name) { this.name = name; } public void setId(int id) { this.id = id; } public void setAge(int age) { this.age = age; } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() {return name; } public int getId() { return id; } public int getAge() { return age; } @Override public String toString() { return "User{" + "name='" + name + ''' + ", id=" + id + ", age=" + age + '}'; }}Copy the code

In Java, each Class has its own Class object, and when we write a.java file and compile it using Javac, we create a.class bytecode file, which contains all the information about the Class, such as properties, constructors, When the bytecode file is loaded into the virtual machine for execution, an in-memory Class object is generated that contains all the information inside the Class, which is available at runtime.

Get the class object

  • The name of the class. The class: This method of obtaining only incompileThe Class object can be obtained only if the type of the Class has been declared
Class c1 = Class.forName("reflection.User");
Copy the code
  • Class.forName(className): by classFully qualified nameGets the Class object for that Class
Class c1 = Class.forName("reflection.Student2");
Copy the code
  • Instance. GetClass (): Gets the Class object of the instance by instantiating the object
User user = new User();
Class aClass = user.getClass();
Copy the code

So after obtaining the class object we can do a lot of things, after all, the class object has all the information of a class, we can naturally obtain the class variables, methods, class information and so on. It can even crack the original private permission set by the class….

  • Class is itself a Class
  • Class objects can only be created by the system
  • A loaded Class will only have one Class instance in the JVM
  • A Class object corresponds to a.class file loaded into the JVM
  • Each instance of a Class remembers which Class instance it was generated from
  • Class provides a complete view of all loaded structures in a Class
  • The Class Class is the root of Reflection, and for any Class that you want to dynamically load and run, you have to get the corresponding Class object first

Instantiate objects by reflection

When we didn’t learn reflection, we used to create a new object, so now we can instantiate a class object using a class object.

There are two ways to construct an instance of a class by reflection:

  • Class object callnewInstance()Method (deprecated in the new version, this method calls a constructor with no arguments, so you need to add a constructor with no arguments on the User class, otherwise it will raise an exception)
User user = (User) c1.newInstance();
System.out.println(user);
Copy the code

  • Constructor callnewInstance()Method (this is the preferred method and can be passed in parameters as needed to control the call to the parameterized constructor)
The User user2 = (User) c1. GetDeclaredConstructor (String class, int. J class, int. J class). NewInstance (" qian-li ma ", 1, 25); System.out.println(user2);Copy the code

Get information about a class through class

The main information of a class is the information listed in the diagram. How do we get this information from the class object?

Get a variable in a class (Field)

Class objects have several common methods:

  • Field[] getFields() : Gets all variables in a class that are modified by public

  • Field getField(String name) : Gets a variable in a class based on the variable name, which must be public

  • Field[] getDeclaredFields() : getDeclaredFields() : getDeclaredFields() : getDeclaredFields() : getDeclaredFields() : getDeclaredFields() : getDeclaredFields() : getDeclaredFields() : getDeclaredFields() : getDeclaredFields()

  • Field getDeclaredField(String name) : Obtains a variable from a class by name, cannot obtain an inherited variable

// Execute the reflection attribute User user4 = (User) c1.newinstance (); Field name = c1.getDeclaredField("name"); // Can not directly access the private property, turn off the program security detection, property or method name.setaccessible (true); Set (user4," tian Haochen "); // Close the program security check, property or method name.set(user4," Tian Haochen "); System.out.println(user4.getName());Copy the code

Here we also use a Field. SetAccessible method to turn off the program’s security check mechanism, which can be turned off without requiring the program to check permissions, thus improving the efficiency of the program, which we won’t explain here

Get a Method from a class

// Invoke the normal method User user3 = (User) c1.newinstance (); // System.out.println(age); Method setName = c1.getMethod("setName", string.class); //invoke (object," method value ") setName.invoke(user3," Zhao Yixin "); System.out.println(user3.getName());Copy the code

Get the Constructor of the class

  • Constuctor[] getConstructors() : Gets all the objects in a classpublicModified constructor
  • Constructor getConstructor(Class… <? > paramTypes) : according toThe parameter typesGets a constructor in a class that must be used bypublicmodified
  • Constructor[] getDeclaredConstructors() : Gets all constructors in a class
  • Constructor getDeclaredConstructor(class… <? > paramTypes) : according toThe parameter typesGets the corresponding constructor

Each function is internally subdivided into 2 classes using Declared:

Methods with Declared modifiers: all variables, methods, and constructors contained inside the class can be obtained, but inherited information cannot be obtained

Methods without Declared modifiers: It is possible to obtain the variables, methods, and constructors that are publicly modified in the class and obtain inherited information

Get an Annotation

Getting an annotation is a separate matter because it is not specific to a Class object. Every variable, Method, and Constructor can be annotated, so in reflection, Field, Constructor, and Method Class objects can call the following methods to get the annotation annotated on them.

  • Annotation[] getanannotations () : Retrieves all annotations on this object
  • Annotation getAnnotation(Class annotaionClass) : incoming notationAnnotation typeGets a specific annotation on the object
  • Annotation[] getDeclaredanannotations () : Retrieves all annotations of the explicit annotations on this object and cannot be retrievedinheritanceThe following notes
  • Annotation getDeclaredAnnotation(Class Annotation Class) : based onAnnotation typeRetrieves a specific annotation on this objectinheritanceThe following notes

The @retension annotation is only available through reflection if the annotation is RUNTIME. There are three preservation strategies for @Retension:

  • SOURCE: only in the ** source file (.java)**, that is, the annotation will only remain in the source file,The compiler ignores this annotation at compile time, such as the @override annotation
  • CLASS: stored in aBytecode files (.class)Annotations will follow the bytecode file along with compilation, howeverThe runtimeThis annotation will not be parsed
  • RUNTIME: Saved untilThe runtime.The most commonly used save strategyAll information about the annotation is available at run time

To obtain a generic

GetGenericParameterTypes getGenericParameterTypes getGenericParameterTypes getGenericParameterTypes getGenericParameterTypes getGenericParameterTypes getGenericParameterTypes getGenericParameterTypes getGenericParameterTypes getGenericParameterTypes You need to iterate over it once, and then call getActualTypeArguments to get its true type.

Method method = test11.class.getMethod("test1", Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); For (Type genericParameterType: genericParameterTypes) {system.out.println ("*"+genericParameterType); if(genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } System.out.println("---------------------------"); method = test11.class.getMethod("test2",null); Type genericReturnType = method.getGenericReturnType(); if(genericReturnType instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); }}Copy the code

Practice: Customize comments and get comment information through reflection

Class c1 = Class.forName("reflection.Student2"); Annotations [] annotations = c1.getannotations (); for (Annotation annotation : annotations) { System.out.println(annotation); } // Get the value of the annotation Tablema Tablema = (Tablema) c1.getannotation (tablema.class); System.out.println(tablema.value()); Field f = c1.getDeclaredField("name"); Fieldma annotation = f.getAnnotation(Fieldma.class); System.out.println(annotation.columnName()); System.out.println(annotation.Type()); System.out.println(annotation.length());Copy the code
@Tablema("db_student")
class Student2{
    @Fieldma(columnName = "db_id", Type = "int" ,length = 10)
    private int id;
    @Fieldma(columnName = "db_age", Type = "int" ,length = 10)
    private int age;
    @Fieldma(columnName = "db_name", Type = "varchar" ,length = 3)
    private String name;

    public Student2() {
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + ''' +
                '}';
    }
}
Copy the code
@target (elementtype.type) @retention (retentionPolicy.runtime) @interface Tablema{String value(); @target (elementtype.field) @Retention(retentionPolicy.runtime) @interface Fieldma{String columnName(); String Type(); int length(); }Copy the code

So that’s the end of reflection, quoted in the article: Programmer Cxuan

Links:Juejin. Cn/post / 686432…Assault delete.