Do programmers really understand the reflex mechanism?



Many blog posts explaining reflection do not elaborate on the Class class, ~including me before of course,~. Such posts only make reflection superficial, and do not really let most beginners understand reflection. The principle of reflection is just the Class object!So his importance is obvious. This article I will summarize the knowledge about Class class, which may not be very comprehensive. You should wait for Ha QnQ. I have written several articles about reflection before. The main point is that reflection is really important. Now I will recapsulate one article ~mainly the summary of the previous one is too scratchy~. Recognize the reflection again and combine some excellent articles to recapitulate it..

Reference material:



1. Overview of reflection

A sentence defining reflection is when you know at runtime what class you want to operate on, and you can get the complete construction of the class at runtime and call the corresponding method. Reflection is actually a byte code file that gets the class, that is, a.Class file.Usually, when we call a method in a class, we need to create an object of that class. By calling a method in a class through an object, reflection does not know at first what the class object I want to initialize is, nor can we use the new keyword to create an object. In this case (no object is created), we can call its methods and properties.This ability to dynamically obtain object information and invoke object methods is called a reflection mechanism.

Reflection reflects how java creates objects.When a java virtual machine (JVM) loads a class class file, a class object of this class is created, and subsequent objects are created by this class object, so all objects of the same class have a class object, such as A=new A(); A=new A(); A.class()==b.class() returns true.


Many blog posts explaining reflection do not elaborate on the Class class, ~including me before, of course ~. Such articles do not really let most beginners understand reflection, but rather the principle of reflection is the Class object!So it's important to see that this article will summarize the knowledge about Class class, which may not be very comprehensive yet. Please wait a moment.

First, I want to give beginners or Xiao Bai some understanding of the Class lass.Common classes are String class, Math class and so on, where Class is also a class like String class, Math class and so on, which is fundamentally different from the concept of the class we create at will. Class class is under the java.lang package!

As you know, a class consists of member variables, methods, construction methods, packages, field attributes, and so on. Reflection maps all the components of a Java class into one Java object, which can be understood as "dissecting" a class using reflection technology and mapping each component into one object.In fact, these member methods, constructors, and joining classes in a class all have a Class class to describe. Before using reflection formally, it is necessary to first understand this Class class!

Reflection works on Class objects

2.1. Loading process of common classes

Familiarize yourself with loading: Class objects are designed to read class files into memory and create a Class object for them.The essence of reflection is to retrieve all kinds of component information (including member variables, methods, construction methods, packages, field attributes, etc.) of the Student object after getting the Class object. Here is an example of the Student object to illustrate the normal loading process of the Student class.

You can see that this Class object is special in the diagram.Let's take a closer look at this Class class!

2.2. API for Analyzing Class Classes (API 1.7)

Instances of Class classes represent classes and interfaces in a running Java application.That is, there are more than N instances in the JVM and each class has the Class object.Class (including basic data types) does not have a public construct.Class objects are automatically constructed when classes are loaded by the Java virtual machine and by calling the defineClass method in the class loader.That is, we don't need to deal with creating Class objects on our own; the JVM has already created them for us.

2.3. Common methods of Class classes

Class classes do not have a common construction method. JVM will automatically help us create them, but there are 64 methods. Here, we will mainly talk about the common methods.

1. getName(): Returns the name of the entity (class, interface, array class, base type, or void) represented by this Class object

A Class object describes the properties of a particular class, and the most common method in a Class class, getName, returns the Class as a String
The name of the entity (class, interface, array class, base type, or void) represented by the object.

2. newInstance(): Create an instance of the class, but only call the default constructor (parameterless constructor)

Class also has a useful way to create an instance of a class, called newInstance().For example:
x.getClass.newInstance(), which creates a new instance of the same type as x.The newInstance() method can only call the default constructor (parameterless constructor) to initialize a new object.


The getClassLoader() method mainly returns the class loader for that class.


The getComponentType() method mainly returns a Class that represents an array component type.


getSuperclass() returns a Class that represents the superclass of the entity (class, interface, base type, or void) represented by this Class.


isArray() determines whether this Class object represents an array class.

One thing to note is that forName and newInstance work together to create objects based on class names stored in strings using the Class.forName() method, which is explained separately below.for example

Object obj = Class.forName(s).newInstance();

In addition, the virtual machine manages a unique Class object for each type, that is, the Class object is unique.So you can use the ==operator to compare class objects.For example:

if(e.getClass() == Employee.class)...

2.4, Class.forName() method

Class.forName() is a static method for getting Class objects.

Class.forName() is a static method that can also be used to load classes, and Class.forName() returns a Class object of the class or interface associated with a given string name.Note that this is a way to get a Class object

The official API documentation is as follows

publicstatic Class<?> forName(String className)

Returns the Class object associated withthe class or interface with the given string name. Invokingthis method is equivalent to:

Class.forName(className,true, currentLoader)

where currentLoader denotes the definingclass loader of the current class.

For example, thefollowing code fragment returns the runtime Class descriptor for theclass named java.lang.Thread:

Class t =Class.forName("java.lang.Thread")

A call to forName("X") causes theclass named X to beinitialized.


className - the fully qualifiedname of the desired class.


the Class object for the classwith the specified name.

You can see that Class.forName(className) actually calls Class.forName(className,true, this.getClass().getClassLoader()).The second parameter refers to whether the Class must be initialized after it is loaded.You can see that the class is initialized when it is loaded using Class.forName(className).So the Class.forName() method can be simply understood as getting the class specified in the string parameter and initializing it.

2.5. Questions on Class Class

1. What is the main difference between the newInstance() method and the new keyword when initializing a class and generating an instance?

The difference is that objects are created differently, using the class loading mechanism and creating a new class.

2. Why are there two ways to create objects?

This mainly considers software design ideas such as scalability, scalability and reusability.Factory mode in Java often uses the newInstance() method to create objects, so you can find out why you want to use factory mode.For example, the following code

  class c = Class.forName("Example");  

factory = (ExampleInterface)c.newInstance();  

ExampleInterface is the interface of Example, which can be written as follows:

 String className = "Example";  

  class c = Class.forName(className);  

  factory = (ExampleInterface)c.newInstance();  

It can be further written as follows:

 String className = readfromXMlConfig;//Get string from xml configuration file

         class c = Class.forName(className);  

         factory = (ExampleInterface)c.newInstance();  

The class name of Example no longer exists in the code above. The advantage is that no matter how the Example class changes, the code above will not change, and even Example's siblings Example2, Example3, Example4..., as long as they inherit ExampleInterface.
3. From the JVM perspective, when we create a class with the keyword new, it may not be loaded.However, when using the newInstance() method, you must ensure that:

1. This class has already been loaded;
2. This class is already connected.

It is the static method forName() of Class that completes the above two steps, which calls the launching class loader, the one that loads the java API.Now you can see that newInstance() actually breaks up the new approach into two steps, first loading a class by calling the Class load method, then instantiating it.The benefits of this step-by-step approach are obvious.We have more flexibility in calling the class static load method forName, which provides a means of decoupling.

4. A very common use of Class.forName when loading a database driver is when loading a database driver, the code is as follows:

Connection con=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName==NP","jph","jph");    

Why don't we call the newInstance() method when we load the database driver package?Class.forName(xxx.xx.xx) is one of the existing jdbc connection database writings; however, there are a few: Class.forName (xx xx.xx.xx). newInstance(), why are these two writings?

As mentioned earlier, the purpose of Class.forName(") is to require the JVM to find and load the specified class, and if there is a static initializer in the class, the JVM must execute a static snippet of the class.The JDBC specification explicitly requires that this Driver class register itself with DriverManager, that is, the code for any JDBCDriver Driver class must be similar to the following:

 public classMyJDBCDriver implements Driver {
         DriverManager.registerDriver(new MyJDBCDriver());

Now that the static initializer is registered, all we need to do with JDBC is Class.forName(XXX.XXX); that's it.

5. Finally, use the simplest description to distinguish between the new keyword and the newInstance() method:

  1. newInstance: Weak type.Poor efficiency.Only parameterless constructs can be called.
  2. new: Strong type.Relatively efficient.Any public construct can be invoked.

At this point, the Class class is almost ready to learn to use reflection.

3. Use of reflection

In JDK, reflection-related API s can be divided into the following aspects: acquiring reflected lass objects, creating Class objects through reflection, acquiring Class properties through reflection, methods and constructors.

3.1. Three ways to get Class objects

For why the first step is to get a Class object, because I mentioned earlier that the essential understanding of reflection is to retrieve the various component information of a Student object (including member variables, methods, construction methods, package, field properties, etc.) after getting a Class object, so the first step of reflection is to get a Class object of the class that needs to be reflected.

1. Use Class.forName static method.
When you know the full path name of the class, you can use this method to get the Class object (most commonly, you must know it)
2. Use the.class method.
This method is only suitable for a Class that knows what to do before compiling, but it requires the package of the class to be imported, which is so dependent that it uses slightly less than the first one [Emphasis]
3. Use the getClass() method of the class object.
This method has already created an object, so there is no need to reflect at this time, which is a bit redundant.[Not often, just know it]

//First, use the Class.forName static method.
Class Student= Class.forname("com.FanSe.Student");//Full path name of class

//Second, use the.class method.
Class Student= Class name.class;//This method requires importing a package of classes, which is too dependent

//Third, use the getClass() method of the class object.
Student str = new Student();
Class clz = str.getClass();

Summary: The first Class.forName static method is commonly used in development, which can be passed in as a string (the full path name of a class) or written in a configuration file.Also note that during run time, only one Class object is generated for a class.

3.2. Reflection acquisition construction method and use

1). Batch acquisition construction method:
public Constructor[] getConstructors(): All "public" construction methods

public Constructor[] getDeclaredConstructors(): Get all constructs (including private, protected, default, public)

2). Get a single method and call:
public Constructor getConstructor(Class... parameterTypes): Get a single "public" construction method:
public Constructor getDeclaredConstructor(Class... parameterTypes): Getting a "construction method" can be private or protected, default, public;

3) Call the construction method:
Constructor-->newInstance(Object... initargs)

NewInstance is a method of the Constructor class (a class that manages constructors), and the api is interpreted as: newInstance(Object... initargs), a constructor represented by this Constructor object is used to create a new instance of the declared class of the constructor, and the instance is initialized with the specified initialization parameters.Its return value is of type T, so newInstance is a new instance object that creates a declarative class for a constructor.And call for it.

Reflection Get Construction Method Summary: When we go to get a class constructor, if we want to get a private method or a private constructor, we must use a method with the declared keyword.[Of course, it's not just the constructor, but the same way to get class methods, class properties, and declared keywords]

Begin the code-in-practice phase below

Create a generic Student class

package fanshe;
public class Student {
    //------------------ Construction Method-----------------------
    //(default construction method)
    Student(String str){
        System.out.println("(default)Construction methods s = " + str);
    //Parameterless construction method
    public Student(){
        System.out.println("The public parameterless construction method was called to execute.");
    //A construction method with one parameter
    public Student(char name){
        System.out.println("Full name:" + name);
    //Construction methods with multiple parameters
    public Student(String name ,int age){
        System.out.println("Full name:"+name+"Age:"+ age);//There is a problem with the efficiency of this implementation and it will be resolved later.
    //Protected construction methods
    protected Student(boolean n){
        System.out.println("Protected construction methods n = " + n);
    //Private construction methods
    private Student(int age){
        System.out.println("Private method age:"+ age);

Writing test classes

package fanshe;
import java.lang.reflect.Constructor;
 * Class objects allow you to get the construction methods, member variables, member methods in a class, and access members.
 * 1.Get the construction method:
 *      1).Batch method:
 *          public Constructor[] getConstructors(): All "public" construction methods
            public Constructor[] getDeclaredConstructors(): Get all constructs (private, protected, default, public)
 *      2).Get a single method and call:
 *          public Constructor getConstructor(Class... parameterTypes):Get a single "public" construction method:
 *          public Constructor getDeclaredConstructor(Class... parameterTypes):Getting a "construction method" can be private or protected, default, or public;
 *          Call the construction method:
 *          Constructor-->newInstance(Object... initargs)
public class Constructors {
    public static void main(String[] args) throws Exception {
        //1. Loading Class Objects
        Class clazz = Class.forName("fanshe.Student");
        //2. Get all public construction methods
        System.out.println("**********************All public construction methods*********************************");
        Constructor[] conArray = clazz.getConstructors();
        for(Constructor c : conArray){
        System.out.println("************All construction methods(Includes: Private, Protected, Default, Public)***************");
        conArray = clazz.getDeclaredConstructors();
        for(Constructor c : conArray){
        System.out.println("*****************Getting public, parameterless construction methods*******************************");
        Constructor con = clazz.getConstructor(null);
        //1>, because it is a parameterless construction method, the type is null, or it can be written without: what you need here is the type of a parameter, remember that it is a type
        //2>, returns a class object that describes this parameterless constructor.
        System.out.println("con = " + con);
        //Call Construction Method
        Object obj = con.newInstance();
    //  System.out.println("obj = " + obj);
    //  Student stu = (Student)obj;
        System.out.println("******************Get the private constructor and call it*******************************");
        con = clazz.getDeclaredConstructor(char.class);
        //Call Construction Method
        con.setAccessible(true);//Violent access (ignoring access modifiers)
        obj = con.newInstance('male');

test result

**********************All public construction methods*********************************
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
************All construction methods(Includes: Private, Protected, Default, Public)***************
private fanshe.Student(int)
protected fanshe.Student(boolean)
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
*****************Getting public, parameterless construction methods*******************************
con = public fanshe.Student()
//The public parameterless construction method was called to execute.
******************Get the private constructor and call it*******************************
public fanshe.Student(char)
//Name: Male

3.3. Reflection takes member variables and calls them

Create Student Class

package fanshe.field;
public class Student {
    public Student(){
    public String name;
    protected int age;
    char sex;
    private String phoneNum;
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", sex=" + sex
                + ", phoneNum=" + phoneNum + "]";

Test Class

package fanshe.field;
import java.lang.reflect.Field;
 * Get the member variable and call:
 * 1.Batch
 *      1).Field[] getFields():Get all Public Fields
 *      2).Field[] getDeclaredFields():Get all fields, including: private, protected, default, public;
 * 2.Get a single:
 *      1).public Field getField(String fieldName):Gets a "public" field;
 *      2).public Field getDeclaredField(String fieldName):Get a field (which can be private)
 *   Set the value of the field:
 *      Field --> public void set(Object obj,Object value):
 *                  Parameter description:
 *                  1.obj:The object of the field to be set;
 *                  2.value:The value to be set for the field;
public class Fields {
        public static void main(String[] args) throws Exception {
            //1. Get Class Objects
            Class stuClass = Class.forName("fanshe.field.Student");
            //2. Get Fields
            System.out.println("************Get all public fields********************");
            Field[] fieldArray = stuClass.getFields();
            for(Field f : fieldArray){
            System.out.println("************Get all fields(Including private, protected, default)********************");
            fieldArray = stuClass.getDeclaredFields();
            for(Field f : fieldArray){
            System.out.println("*************Get Public Fields**And call***********************************");
            Field f = stuClass.getField("name");
            //Get an object
            Object obj = stuClass.getConstructor().newInstance();//Generate Student Object --"Student stu = new Student();
            //Set values for fields
            f.set(obj, "Lau Andy");//Assign a value to the name attribute in the Student object--" ="Liu Dehua"
            Student stu = (Student)obj;
            System.out.println("Verify name:" +;
            System.out.println("**************Get Private Fields****And call********************************");
            f = stuClass.getDeclaredField("phoneNum");
            f.setAccessible(true);//Violent Reflex, Release Private Limitation
            f.set(obj, "18888889999");
            System.out.println("Verify Phone:" + stu);

Test results

**************Get all public fields**************
public java.lang.String
 **************Get all fields (including private, protected, default)****************
public java.lang.String
protected int fanshe.field.Student.age
private java.lang.String fanshe.field.Student.phoneNum
 *************Get public fields** and call *****************************
public java.lang.String
 Verify name: Andy Lau
 ****************Get Private Fields**** and Call**************************
private java.lang.String fanshe.field.Student.phoneNum
 Verification phone: Student [name=Liu Dehua, age=0, sex=

Thus, when calling a field, you need to pass two parameters:
Object obj =stuClass.getConstructor().newInstance();//Produce Student Object--"Student stu = new Student();//Set value f.set(obj,"Liu Dehua") for field; //Assign value to name attribute in Student object--" = "Liu Dehua"
The first parameter: to pass in the set object, the second parameter: to pass in the argument

3.4. Reflect to get member method and call

Create student class

package fanshe.method;
public class Student {
    //****************Member Method*******************//
    public void show1(String s){
        System.out.println("Called: Public, String Parametric show1(): s = " + s);
    protected void show2(){
        System.out.println("Called: Protected, parameterless show2()");
    void show3(){
        System.out.println("Called: Default, no parameter show3()");
    private String show4(int age){
        System.out.println("Called, private, and has a return value, int Parametric show4(): age = " + age);
        return "abcd";

Writing test classes

package fanshe.method;
import java.lang.reflect.Method;
 * Get the member method and call:
 * 1.Batch:
 *      public Method[] getMethods():Get all public methods; (Methods containing parent classes also contain Object classes)
 *      public Method[] getDeclaredMethods():Get all member methods, including private (excluding inherited)
 * 2.Get a single:
 *      public Method getMethod(String name,Class<?>... parameterTypes):
 *                  Parameters:
 *                      name : Method name;
 *                      Class ... : Class-TYPE OBJECT FOR FORMAL PARAMETERS
 *      public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
 *   Call method:
 *      Method --> public Object invoke(Object obj,Object... args):
 *                  Parameter description:
 *                  obj : The object to call the method;
 *                  args:Arguments passed when calling the method;
public class MethodClass {
    public static void main(String[] args) throws Exception {
        //1. Get Class Objects
        Class stuClass = Class.forName("fanshe.method.Student");
        //2. Get all public methods
        System.out.println("***************Get All Public Methods*******************");
        Method[] methodArray = stuClass.getMethods();
        for(Method m : methodArray){
        System.out.println("***************Get all methods, including private*******************");
        methodArray = stuClass.getDeclaredMethods();
        for(Method m : methodArray){
        System.out.println("***************Get Public show1()Method*******************");
        Method m = stuClass.getMethod("show1", String.class);
        //Instantiate a Student object
        Object obj = stuClass.getConstructor().newInstance();
        m.invoke(obj, "Lau Andy");
        System.out.println("***************Get Private show4()Method******************");
        m = stuClass.getDeclaredMethod("show4", int.class);
        m.setAccessible(true);//Release Private Limitation
        Object result = m.invoke(obj, 20);//Two parameters are required, one for the object to be invoked (get reflected) and one for the argument
        System.out.println("Return value:" + result);

Test results:

***************Get All Public Methods*******************
public void fanshe.method.Student.show1(java.lang.String)
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) 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()
***************Get all methods, including private*******************
public void fanshe.method.Student.show1(java.lang.String)
private java.lang.String fanshe.method.Student.show4(int)
protected void fanshe.method.Student.show2()
void fanshe.method.Student.show3()
***************Get Public show1()Method*******************
public void fanshe.method.Student.show1(java.lang.String)
//Called: Public, show1(): s = Liu Dehua for String parameter
***************Get Private show4()Method******************
private java.lang.String fanshe.method.Student.show4(int)
//Called, private, and returned, show4() for the int parameter: age = 20
//Return value: abcd

Thus it can be seen:
m = stuClass.getDeclaredMethod("show4", int.class);//A call to a development method (all including private) requires two parameters to be passed in, the first being the name of the method being invoked, and the second being the parameter type of the method, remember the type.
m.setAccessible(true);//Release Private Limitation
Object result = m.invoke(obj, 20);//Two parameters are required, one for the object to be invoked (get reflected) and one for the argument
System.out.println("Return value:" + result);

3.5. Reflection main method

Student class

package fanshe.main;
public class Student {
    public static void main(String[] args) {
        System.out.println("main Method executed.");

Writing test classes

package fanshe.main;
import java.lang.reflect.Method;
 * Get the main method of the Student class, don't confuse with the current main method
public class Main {
    public static void main(String[] args) {
        try {
            //1. Get the byte code of the Student object
            Class clazz = Class.forName("fanshe.main.Student");
            //2. Get main method
             Method methodMain = clazz.getMethod("main", String[].class);//The first parameter is the method name, and the second parameter is the type of the method parameter.
            //3. Call main method
            // methodMain.invoke(null, new String[]{"a","b","c"});
             //The first parameter, the object type, is null because the method is static, and the second parameter is a String array. Note here that jdk1.4 is an array, and after jdk1.5 is a variable parameter
             //new String[]{"a","b","c"} is split into three objects when it is split here.So you need to turn it around.
             methodMain.invoke(null, (Object)new String[]{"a","b","c"});//Mode 1
            // methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}); //Mode 2
        } catch (Exception e) {

test result

The main method executes.

3.6. Other uses of reflection methods - running profile content through reflection

public class Student {
    public void show(){
        System.out.println("is show()");

Configuration files take the txt file as an example (pro.txt):

className = cn.fanshe.Student
methodName = show

demo class

import java.lang.reflect.Method;
import java.util.Properties;
 * With reflection and configuration files, we can make: application updates without any modifications to the source code
 * We just need to send the new class to the client and modify the configuration file
public class Demo {
    public static void main(String[] args) throws Exception {
        //Getting Class Objects by Reflection
        Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
        //2 Get show() method
        Method m = stuClass.getMethod(getValue("methodName"));//show
        //3. Call show() method
    //This method receives a key and gets the corresponding value in the configuration file
    public static String getValue(String key) throws IOException{
        Properties pro = new Properties();//Object to get profile
        FileReader in = new FileReader("pro.txt");//Get Input Stream
        pro.load(in);//Loading streams into profile objects
        return pro.getProperty(key);//Returns the value obtained from the key


is show()

When we upgrade this system, instead of the Student class, we need to write a new Student2 class, so we just need to change the contents of the pro.txt file.The code doesn't need to be changed at all

The student2 class to replace:

public class Student2 {
    public void show2(){
        System.out.println("is show2()");

Change the configuration file to:

className = cn.fanshe.Student2
methodName = show2

Console Output:

is show2();

3.7. Other uses of reflection methods - passing generic checks by reflection

Generics are used at compile time and are erased (disappeared) after compilation.So it's possible to pass the generic check by reflection
Test class:

import java.lang.reflect.Method;
import java.util.ArrayList;
 * Bypass Generic Check by Reflection
 * For example, if you have a collection of String generics, how can you add an Integer type value to it?
public class Demo {
    public static void main(String[] args) throws Exception{
        ArrayList<String> strList = new ArrayList<>();
    //  strList.add(100);
        //Get the lass object of ArrayList, invoke the add() method in reverse, add data
        Class listClass = strList.getClass(); //Gets the byte code object of the strList object
        //Get the add() method
        Method m = listClass.getMethod("add", Object.class);
        //Call the add() method
        m.invoke(strList, 100);
        //Traverse Set
        for(Object obj : strList){

Console Output:


Another article about my reflection Java Foundation Focus - Getting Started with Reflection Mechanisms and Using them , the writing is not good, but you can also refer to the comparison to see, or good.

Finally, I would like to welcome all of you to pay attention to my public number, discuss technology together, yearn for technology, and pursue technology. Well, you're friends now.

Tags: Java jvm JDBC Database

Posted on Sun, 10 Nov 2019 19:42:35 -0500 by copernic67