Java Reflection Mechanism 2019/8/2

Keywords: Java jvm Attribute less

I. Introducing the Concept of Reflection

In the running state, for any class, we can wait until the class has any methods and attributes; for any object, we can call until its methods and attributes. We call this function of dynamic acquisition of object information and invoking object methods a reflection mechanism.

2. Reflective function

1. Get the properties of an object.
2. Get the static properties of a class.
3. The method of executing an object.
4. Execute static methods for a class.
5. Instances of new classes.

3. Getting Class Objects

After each class is loaded, the system generates a corresponding Class object for the class, through which the class in the JVM can be accessed. There are three ways to obtain Class objects in Java programs:
1. Use the forName(String className) static method of the Class class. This method needs to pass in a string parameter whose value is the fully qualified class name of a class (the full package name must be added). Class.forName(String className); (most commonly used)
2. Call the class attribute of a class to get the corresponding Class object of that class. For example, className.class will return the Class object corresponding to the className. className.class;
3. Call the getClass() method of an object. This method is a method in the java.lang.Object class, so all Java objects can call this method. This method will return the Class object corresponding to the class to which the object belongs. new className().getClass();
ps: For both the first and the second methods, Class objects of this class are obtained directly from the class. In contrast, the second method has two advantages (code is safer: the program can check whether the Class objects that need to be accessed exist at the compilation stage). Program performance is better: because this method does not need to call methods, so the performance is better.)

4. Common Applications

The following is to obtain the Class object corresponding to the ClassTest class for the program, and obtain the detailed information of the Class object by calling different methods of the Class object:

public class ClassTest {
    private ClassTest(){}
    public ClassTest(String name){
        System.out.println("Perform a parameterized constructor");
    }
    public void info(){
        System.out.println("Executing parametric info Method");
    }
    public void info(String str){
        System.out.println("Perform parameterized info Method"+",his str The value is:"+str);
    }
    class Inner{}
    public static void main(String[] args) throws Exception{
        Class<ClassTest> clazz=ClassTest.class;
        Constructor[] ctors=clazz.getDeclaredConstructors();
        System.out.println("ClassTest All constructors are as follows:");
        for(Constructor c:ctors){
            System.out.println(c);
        }
        Constructor[] publicCtors=clazz.getConstructors();
        System.out.println("ClassTest All public The constructors are as follows:");
        for(Constructor c:publicCtors){
            System.out.println(c);
        }
        Method[] mtds=clazz.getMethods();
        System.out.println("ClassTest All public The methods are as follows:");
        for(Method md:mtds){
            System.out.println(md);
        }
        System.out.println("ClassTest With a string parameter in it info The methods are as follows:"+clazz.getMethod("info",String.class));
        Class<?>[] inners=clazz.getDeclaredClasses();
        System.out.println("ClassTest All internal categories are as follows:");
        for(Class c:inners){
            System.out.println(c);
        }
        Class inClazz=Class.forName("ClassTest$Inner");
        System.out.println("inClazz The external classes of the corresponding classes are:"+inClazz.getDeclaringClass());
        System.out.println("ClassTest The package is:"+clazz.getPackage());
        System.out.println("ClassTest The parent class is"+clazz.getSuperclass());
    }
}
//Output results:
ClassTest All constructors are as follows:
private ClassTest()
public ClassTest(java.lang.String)
ClassTest All public The constructors are as follows:
public ClassTest(java.lang.String)
ClassTest All public The methods are as follows:
public static void ClassTest.main(java.lang.String[]) throws java.lang.Exception
public void ClassTest.info(java.lang.String)
public void ClassTest.info()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
ClassTest With a string parameter in it info The methods are as follows: public void ClassTest.info(java.lang.String)
ClassTest All internal categories are as follows:
class ClassTest$Inner
inClazz The external classes of the corresponding classes are: class ClassTest
ClassTest The package is: package 
ClassTest The parent class is class java.lang.Object

Not only these methods, but many others can be viewed by consulting the API documentation.

Reflection can also bypass generics checks, as follows:

public class QAQTest {
    public static void main(String[] args) throws Exception{
        ArrayList<String> list=new ArrayList<>();
        list.add("???");
        list.add("!!!");
        /*Write a list.add(5) error report here*/
        /*Get the Class es object of ArrayList and invoke the add() method in reverse*/
        Class listClass=list.getClass();
        //Get the add() method
        Method m=listClass.getMethod("add",Object.class);
        //Call the add() method
        m.invoke(list,5);
        for(Object obj:list){
            System.out.println(obj);
        }
    }
}
//Output results:
???
!!!
5

V. Characteristics of Reflection

Although reflection mechanism brings great flexibility and convenience, it also has many shortcomings. The function of reflection mechanism is very powerful, but it can not be abused. It can be done without reflection.

  • Performance issues: The Java reflection mechanism contains some dynamic types, so the Java virtual machine cannot optimize these dynamic codes. Therefore, the efficiency of reflection operation is much lower than that of normal operation. We should avoid using reflection in highly performance-demanding programs or code that is often executed. And how to use reflection determines the performance. If it is part of a program that runs less, performance will not be a problem.
  • Security restrictions: The use of reflection usually requires that the program run without security restrictions. If a program requires security, it's best not to use reflection.
  • Program robustness: Reflection allows code to perform operations that are not normally allowed, so using reflection can lead to unexpected consequences. Reflective code destroys the abstraction of Java program structure, so when the platform of program running changes, because the abstract logic can not be recognized, the effect of code will be different from before.

But reflection also has many advantages:

  • Reflection mechanism greatly improves the flexibility and expansibility of the program, reduces the coupling of modules, and improves its adaptability.
  • The reflection mechanism allows the program to create and control objects of any class without hard coding the target class in advance.
  • Using reflection mechanism, we can construct a class object at runtime, judge the member variables and methods of a class, call the method of an object and generate dynamic proxy.
  • Reflection mechanism is the foundation of frameworks technology. Using reflection can avoid writing code to the frameworks.

Posted by webtailor on Fri, 02 Aug 2019 00:37:27 -0700