This is the third day of my participation in the August More text Challenge. For details, see:August is more challenging

Introduction: There are many tripartite frameworks that use reflection. This article will introduce some common reflection apis.

What is reflection?

The Reflection mechanism in Java means that in the running state of a program, you can construct an object of any class, know the class to which any object belongs, know the member variables and methods of any class, and call the properties and methods of any object. This ability to dynamically retrieve program information and dynamically invoke objects is called the Reflection mechanism of the Java language. Reflection is seen as the key to dynamic languages.

The advantages and disadvantages

  • advantages

Reflection improves the flexibility and extensibility of Java programs, reduces the coupling, and improves the adaptive ability. It allows programs to create and control objects of any class without having to hard-code the target class in advance; Reflection is not found in other common languages such as C, C++, Fortran, or Pascal

  • disadvantages
  1. Performance issues: Using reflection is basically an interpreted operation that is much slower for field and method access than for direct code. Therefore, The Java reflection mechanism is mainly applied to the system framework that requires high flexibility and extensibility, and is not recommended for ordinary programs.
  2. Using reflection obviates the internal logic of the program: programmers want to see the logic of the program in the source code, and techniques such as reflection bypass source code and cause maintenance problems. The reflection code is more complex than the corresponding direct code.

In reflection, we don’t know what class object we’re initializing, and we can’t use the new keyword to create the object. In this case, we use the REFLECTION API provided by the JDK to make the reflection call. Reflection is the ability to know, call and change all properties and methods of any given class from the running state.

The Java reflection mechanism provides the following functions:

  1. Construct an object of any class at run time
  2. Gets or modifies the member variables and methods of any class at run time
  3. Call methods (properties) on any object at run time

Getting a Class object

  • Class () Class ()
  • GetClass () getClass()
  • Class.forname (name of the Class) classLoader.loadClass(name of the Class)
public static String str = new String("shixf");
 
    public static void main(String[] args) {
        //1. Obtain the value from the class name
        Class<String> stringClass = String.class;
        //2. Obtain from an object
        Class<? extends String> strClass = str.getClass();
        //3. Obtain the value by the full class name
        try {
            //str.getClass().getName() == java.lang.StringClass<? > aClass = Class.forName(str.getClass().getName()); }catch(ClassNotFoundException e) { e.printStackTrace(); }}Copy the code

Determines whether it is an instance of a class

We often use the “instanceof” keyword to determine whether a Class is an instanceof a Class. We can also use the “isInstance()” method of the Class object in reflection to determine whether a Class is an instanceof a Class, which is a native method.

public native boolean isInstance(Object obj);
 
// Check whether it is of a class type
public native boolean isAssignableFrom(Class
        cls);
Copy the code

Reflection creates an instance object

  • Class.newInstance()
  • Get the Constructor object from Class and create an instance by calling the construction.newinstance () method.
    public static Object createInstance_1(Class cls){
        if(null! = cls){ Object o =null;
            try {
                o = cls.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return o;
        }
        return null;
    }
 
    public static Object createInstance_2(Class cls){
        // Obtain the Class object corresponding to the StringClass<? > c = String.class;// Get the constructor of the String class with a String argument
        Constructor constructor = null;
        // Create an instance according to the constructor
        Object obj = null;
        try {
            constructor = c.getConstructor(String.class);
            obj = constructor.newInstance("23333");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
Copy the code

Get the constructor information

    / * * *@paramparameterTypes ... Represents an array of the type that can be passed, a single instance of it, or no arguments. * Gets the public constructor (including the superclass) */ that uses the particular argument type
    public Constructor<T> getConstructor(Class
       ... parameterTypes)
 
 
    /** * get all public constructors */ for the class
    publicConstructor<? > []getConstructors(a)
 
 
    /** * Get constructors (including private) that use specific parameter types */
    public Constructor<T> getDeclaredConstructor(Class
       ... parameterTypes)
 
 
    /** * get all class constructors */
    publicConstructor<? > []getDeclaredConstructors(a)
Copy the code

Gets information about member variables (fields) of a class

/** * Get the named public field (containing the parent class's public member variables) */
public Field getField(String name)
 
 
/** * get all public fields of the class (including public member variables of the parent class) */
public Field[] getFields(a)
 
 
/** * Get the attribute members of the class itself (private, public, protected) */
public Field getDeclaredField(String name)
 
 
/** * Get all attribute members of the class itself (private, public, protected) */
public Field[] getDeclaredFields(a)
Copy the code

Methods are called by reflection

/** * get a named public method */ with specific parameter types
public Method getMethod(String name, Class
       ... parameterTypes)
 
 
/** * get all public methods */
 public Method[] getMethods(a)
 
 
/** * get the named methods declared by the class, including private. * /
public Method getDeclaredMethod(String name, Class
       ... parameterTypes)
 
/** * gets all named methods declared by the class, including private ones. * /
public Method[] getDeclaredMethods(a)
Copy the code

java.lang.IllegalArgumentException: wrong number of arguments

Note: When we get a method, we can invoke the method by calling the invoke() method. Note the “wrong number of arguments” exception

/ * * * *@param obj
 * @paramArgs Note that this parameter is Object *@return* /
public Object invoke(Object obj, Object... args)
Copy the code
public class GetMethod {
 
    private static GetMethod getMethod = new GetMethod();
    private static String[] strArray = {"1"."2"."3"};
 
 
    public static void main(String[] args) {
        getMethod();
    }
 
    public void printStr(String[] str){
        for(String s : str) { System.out.println(s); }}public static void getMethod(a){ Class<? > cls = getMethod.getClass();try {
            Method printStr = cls.getMethod("printStr",String[].class);
            // Cast to Object, otherwise throw wrong number of arguments
            printStr.invoke(cls.newInstance(),(Object) strArray); 
        } catch(Exception e) { e.printStackTrace(); }}}Copy the code

Use reflection to create arrays

Array is a kind of special type in Java, it can be assigned to an Object Reference of the Array class for Java. Lang. Reflflect. Array class. We create an Array object with array.newinstance (), which has the following prototype:

public static Object newInstance ( Class <? > componentType ,int length );
Copy the code

Reflection gets the true type of a generic

When we reflect on a generic class, we need to get the real data type in the generic to perform operations such as json deserialization. This needs to be done through the Type system. The Type interface contains an implementation Class consisting of four interfaces, which are:

TypeVariable: indicates a generic TypeVariable, which can contain information such as the upper and lower limits of the generic type. ParameterizedType Specifies the Type of the generic signature in the metadata. GenericArrayType Specifies the Type of the generic signature in the metadata. GenericArrayType Specifies the Type of the generic signature when you want to describe an array of generic types, such as List[], map[]. WildcardType Specifies the wildcard generic type to obtain the upper and lower limits.

TypeVariable

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
 
public class TypeVariableTest<K extends Comparable & Serializable.V> {
 
    private K key;
    private V value;
 
    public static void main(String[] args) {
        try {
            Field fKey = TypeVariableTest.class.getDeclaredField("key");
            Field fValue = TypeVariableTest.class.getDeclaredField("value");
            TypeVariable genericTypeKey = (TypeVariable)fKey.getGenericType();
            TypeVariable genericTypeValue = (TypeVariable)fValue.getGenericType();
 
            System.out.println("genericTypeKey.getName(): " + genericTypeKey.getName());
            System.out.println("genericTypeValue.getName(): " + genericTypeValue.getName());
            System.out.println(genericTypeKey.getGenericDeclaration());//class Reflect.TypeVariableTest
            System.out.println(genericTypeValue.getGenericDeclaration());//class Reflect.TypeVariableTest
            System.out.println("The upper bound of K");
            for (Type bound : genericTypeKey.getBounds()) {
                System.out.println(bound);
                //interface java.lang.Comparable
                //interface java.io.Serializable
            }
            System.out.println("Upper bound of V");
            for (Type bound : genericTypeValue.getBounds()) {
                System.out.println(bound);
                //class java.lang.Object}}catch(NoSuchFieldException e) { e.printStackTrace(); }}}Copy the code

ParameterizedType

public class ParameterizedTypeTest {
 
    Map<String, String> mMap;
 
    public static void main(String[] args) {
        try {
            Field map = ParameterizedTypeTest.class.getDeclaredField("mMap");
 
            System.out.println("get mMap GenericType: " + map.getGenericType());//java.util.Map<java.lang.String, java.lang.String>
 
            ParameterizedType pType = (ParameterizedType)map.getGenericType();
            System.out.println(pType.getRawType());//interface java.util.Map
 
            for (Type actualTypeArgument : pType.getActualTypeArguments()) {
                System.out.println(actualTypeArgument);// Two edges class java.lang.string}}catch(NoSuchFieldException e) { e.printStackTrace(); }}}Copy the code

GenericArrayType

public class GenericArrayTypeTest<T> {
 
    List<String>[] lists;
 
    public static void main(String[] args) {
        try {
            Field field = GenericArrayTypeTest.class.getDeclaredField("lists");
            GenericArrayType genericArrayType = (GenericArrayType)field.getGenericType();
            System.out.println(genericArrayType.getGenericComponentType());//java.util.List<java.lang.String>
        } catch(NoSuchFieldException e) { e.printStackTrace(); }}}Copy the code

WildcardType

public class WildcardTypeTest {
 
    private List<? extends Number> up;/ / ceiling
    private List<? super String> down;/ / lower limit
 
    public static void main(String[] args) {
        try {
            Field up = WildcardTypeTest.class.getDeclaredField("up");
            Field down = WildcardTypeTest.class.getDeclaredField("down");
            // Get the generic type first
            ParameterizedType parameterizedTypeUp = (ParameterizedType)up.getGenericType();
            ParameterizedType parameterizedTypeDown = (ParameterizedType)down.getGenericType();
 
            // Get the wildcard type from the generic type
            WildcardType wildcardTypeUp = (WildcardType)parameterizedTypeUp.getActualTypeArguments()[0];
            WildcardType wildcardTypeDown = (WildcardType)parameterizedTypeDown.getActualTypeArguments()[0];
            System.out.println(wildcardTypeUp.getUpperBounds()[0]);//class java.lang.Number
            System.out.println(wildcardTypeDown.getLowerBounds()[0]);//class java.lang.String
 
            System.out.println(wildcardTypeUp);/ /? extends java.lang.Number
        } catch(NoSuchFieldException e) { e.printStackTrace(); }}}Copy the code