Reflection mechanism in java

Posted by haku87 on Tue, 28 Dec 2021 11:23:23 +0100

0. Concept

Reflection Library: a collection of tools that can be used to write programs that dynamically manipulate Java code.

Reflection: a program that can analyze the ability of classes, which can be used to

  1. The ability to analyze classes at run time
  2. Check objects at run time
  3. Implementation of generic array operation code
  4. Using Method objects

 

1. class

1.1 concept

Runtime type identification: the java runtime system always maintains a runtime type identification for all objects. This information will track the class to which each object belongs

Class: use a special java class to access this information (runtime type ID). The class name that saves this information is class

 

1.2 three methods to obtain Class objects

a. Object.getClass method: this method will return an instance of Class type

Employee e;
Class c1 = e.getClass();

The Class object will describe the properties of a specific Class. As described above, c1 can describe the properties of the Class Employee. The most common method is getName(), which will return the name of the Class

e.getClass().getName()

 

 

b. Static method forName: get the Class object corresponding to the type

String className = "java.util.Random";
Class c1 = Class.forName();

 

Only when className is a class name or interface name can this method execute normally, and an exception handler should be provided whenever it is used

 

c. If T is an arbitrary Java type, T.class will represent the matching class object

For example:

 

Class cl1  = Random.class;
Class cl2 = int.class;
Class cl3  = Double[].class;

 

Note: a Class object actually represents a type, which may or may not be a Class. For example, int is not a Class and int.class is an object of Class type

 

1.3 use = = operation to compare the objects of two classes

The virtual machine manages a unique Class object for each type

For example:

if (e.getClass == Employee.class)

 

 

1.4 construct an instance of a description class

If you have an object of Class type, you can use it to construct an instance of the Class

try {
            String className = "java.util.Random";
            Class c1 = Class.forName(className);
            Object obj = c1.getConstructor().newInstance();
            System.out.println(obj);
        } catch (Exception e) {
            e.printStackTrace();
  }

 

Output:

 

 

2. Ability to use reflection analysis class

You can check the structure of the class.

java. In lang.reflect, there are three classes: file, Method and Constructor, which are used to describe the fields, methods and constructors of the class respectively

The three classes share a getName() method that returns the name of a field, method, or constructor.

The following code uses the api of Class to print all the information of a Class

public class ReflectionTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //Read the class name from the command terminal or user input
        String name;
        if (args.length>0) {
            name = args[0];
        }else {
            Scanner in = new Scanner(System.in);
            System.out.println("Enter class name (e.g. java.util.Date):");
            name = in.next();
        }

        //Print the class name and parent class name (not Object (in case of)
        Class cl = Class.forName(name);
        Class superclass = cl.getSuperclass();
        //getModifiers Returns an integer describing the modifier used, using Modifier.toString Method to print the modifier
        String modifier = Modifier.toString(cl.getModifiers());
        if (modifier.length()>0) {
            System.out.print(modifier+" ");
        }
        System.out.print("class "+name);
        if (superclass !=null && superclass != Object.class) {
            System.out.print(" extends "+superclass.getName());
        }
        System.out.print("\n{\n");

        //Print constructor
        printConstructors(cl);
        System.out.println("");
        printMethods(cl);
        System.out.println("");
        printFiled(cl);
        System.out.println("}");

    }

    //Print all constructors of this class
    public static void printConstructors(Class cl){
        //getDeclaredConstructors: Get all constructors
        Constructor[] constructors = cl.getDeclaredConstructors();
        for (Constructor c : constructors) {
            //Gets the name of the constructor
            String name = c.getName();
            System.out.print("   ");
            //Gets the modifier of the constructor
            String modifier = Modifier.toString(c.getModifiers());
            if (modifier.length()>0) {
                System.out.print(modifier+" ");
            }
            System.out.print(name+"(");

            //Print parameter type
            Class[] parameterTypes = c.getParameterTypes();
            for (int i = 0; i <parameterTypes.length ; i++) {
                if (i>0) {
                    System.out.print(", ");
                }
                System.out.print(parameterTypes[i].getName());
            }
            System.out.println(");");

        }
    }


    //Print all methods
    public static void printMethods(Class c1){
        Method[] methods = c1.getMethods();
        for (Method m : methods) {
            //Return type
            Class retType = m.getReturnType();
            String name = m.getName();
            System.out.print("   ");
            String modifier = Modifier.toString(m.getModifiers());
            if (modifier.length()>0) {
                System.out.print(modifier+" ");
            }
            System.out.print(retType.getName()+" "+name+"(");

            //Print all parameter types
            Class[] parameterTypes = m.getParameterTypes();
            for (int i = 0; i <parameterTypes.length ; i++) {
                if (i>0) {
                    System.out.print(", ");
                }
                System.out.print(parameterTypes[i].getName());
            }
            System.out.println(");");

        }
    }


    public static void printFiled(Class cl){
        Field[] fields = cl.getDeclaredFields();
        for (Field f : fields) {
            Class type = f.getType();
            String name = f.getName();
            System.out.print("   ");
            String modifiers = Modifier.toString(f.getModifiers());
            if (modifiers.length() > 0) {
                System.out.print(modifiers+" ");
            }
            System.out.println(type.getName()+" "+name+";");
        }
    }
}

 

 

3. Use reflection to analyze objects at run time

  • Using the reflection mechanism, you can view object fields that are not known during compilation
  • The access to fields is affected by Java security control. The default behavior of the reflection mechanism is limited by Java access control, but you can call the setAccessible method of Field to override Java access control, for example:
f.setAccessible(true);

 

4. Write generic array code using reflection

 java. The Array class in lang.reflect package allows dynamic Array creation

For example, the implementation of CopyOf:

 public static Object goodCopyOf(Object a,int newlength){
        //obtain a Class object of array
        Class cl = a.getClass();
        if(!cl.isArray()) return  null;
        //Determine the correct type of array
        Class componentType = cl.getComponentType();
        int length = Array.getLength(a);
        Object newArray = Array.newInstance(componentType, newlength);
        System.arraycopy(a,0,newArray,0,Math.min(length,newlength));
        return newArray;
    }

 

 

 

5. Use reflection to call methods and constructors

The reflection mechanism allows you to call any Method. There is an invoke Method in the Method class, which allows you to call the Method of the current Method object

 

 Method m1 = Math.class.getMethod("sqrt", double.class);
 double d =(Double) m1.invoke(null, 4);
 System.out.println(d);

 

Output:

 

Topics: Java reflection