java - Getting Started with Reflection

Introduction to reflection

Reflection is an important advanced feature in java and is used in many frameworks. Dynamic proxies are also implemented using reflection.
Reflection allows us to get all the information about a class or object while the program is running. For a class, reflection obtains all its attributes and method information. For an object, we can call all its methods and attributes and understand that reflection is the anatomy of a class.

Four Core Classes of Reflection

1.Class Class

Class class in JDK's java. Under the Lang package, it is the entry for reflection. In java, each class has a corresponding Class object. This Class object is used to represent information about this class and is stored in our javac compiled ** byte code file (.class)**. When we want a new object of this class, the class loader of the JVM loads the corresponding Class object into the JVM (the Class object is stored in the heap, which is the loading of the class). The JVM then creates the instance objects we want based on the information of this Class object.

That is, if we want to know all the information about this class, we need to get this Class object. Class objects are also instance objects of Class classes, so Class classes are the entry for reflection, and only if you get this Class object can you do the next operation. However, Class classes only have private constructors, and we cannot instantiate them directly through the new operator. The corresponding Class object can only be created and loaded by the JVM. Once we have this Class object, we can call the methods in the Class class to get the specified information.

Three ways to get a Class object

// 1. Literal Constants for Class Objects
Class stu = students.class;

/*2. Obtain Class objects by their path names, which is how reflection obtains Class objects
     Class.forName()A ClassNotFoundException needs to be captured because the compiler cannot detect the passing string
     Does the corresponding class exist
 */
Class stu1 = Class.forName("com.reflect.students");

//3. Call the object's getclass method (inherited from the Object class), which requires a new object first
students stu2 = new students();
Class stuclass = stu2.getClass();

//All three methods get the same object because each class in the JVM has a corresponding Class object and only one corresponding Class object

Get Constructor

Constructor<?>[]getConstructors()Get all public constructors for this class
Constructor<?>[]getDeclaredConstructors()Gets all constructors for this class
ConstructorgetDeclaredConstructor(Class<?>... parameterTypes)Gets any constructor specified by a single class
ConstructorgetConstructor(Class<?>... parameterTypes)Gets a single public constructor specified by the class
public class students extends person{
    public String name;
    private String id;
    public int age;
    static int score;
    public students() {
    }

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

    private students(String name, String id) {
        this.name = name;
        this.id = id;
    }
}
@Test
public void reflect_getConstructor() throws NoSuchMethodException, ClassNotFoundException {
    Class stu = Class.forName("com.reflect.students");
    // Constructor<?> [] getConstructors () Gets the constructors for all public s
    for (Constructor con:stu.getConstructors()) {
        System.out.println(con);
    }
    System.out.println("------------");
    //Constructor<?> [] getDeclaredConstructors () Gets all constructors
    for (Constructor con:stu.getDeclaredConstructors()) {
        System.out.println(con);
    }
    System.out.println("------------");
    // Constructor <T> getDeclaredConstructor (Class <?>... parameterTypes) Gets a single specified constructor
    System.out.println(stu.getDeclaredConstructor(int.class));
    System.out.println("------------");
    //Constructor<T> getConstructor (Class<?>... parameterTypes) Gets the constructor for a single specified public
    System.out.println(stu.getConstructor(String.class,String.class,int.class));
}
//------->Output
public com.reflect.students(java.lang.String,java.lang.String,int)
public com.reflect.students()
------------
private com.reflect.students(java.lang.String,java.lang.String)
private com.reflect.students(int)
public com.reflect.students(java.lang.String,java.lang.String,int)
public com.reflect.students()
------------
private com.reflect.students(int)
------------
public com.reflect.students(java.lang.String,java.lang.String,int)

Get Fields

Field[]getFields()Gets the public fields for all this class and all its superclasses
FieldgetField(String name)Gets a single specified public field for this class
FieldgetDeclaredField(String name)Gets a single specified field of this class, which can be private
Field[]getDeclaredFields()Get all fields of this class
public class person {

    public String name;
    private String id;
}
------------------------------------------------------------------------

public class students extends person{

    public String name;
    private String id;
    public int age;
    static int score;
}
@Test
public void reflect_getFieldNames() throws ClassNotFoundException, NoSuchFieldException {
    Class stu = Class.forName("com.reflect.students");
    // Field[] getFields()
    for (Field f:stu.getFields()) {
        System.out.println(f);
    }
    System.out.println("------------");
    // Field getField(String name)
    System.out.println(stu.getField("age"));

    System.out.println("------------");
    // Field[] getDeclaredFields()
    for (Field f:stu.getDeclaredFields()) {
        System.out.println(f);
    }
    System.out.println("------------");
    System.out.println(stu.getDeclaredField("id"));
}
//------->Output
public java.lang.String com.reflect.students.name
public int com.reflect.students.age
    //The public name field of the parent class is also returned
public java.lang.String com.reflect.person.name
------------
public java.lang.String com.reflect.students.name
------------
public java.lang.String com.reflect.students.name
private static java.lang.String com.reflect.students.id
public int com.reflect.students.age
static int com.reflect.students.score
------------
private static java.lang.String com.reflect.students.id

Getting Method

Method[]getMethods()Get the public method for this class and all its superclasses
MethodgetMethod(String name, Class<?>... parameterTypes)Gets the public method specified by the class
Method[]getDeclaredMethods()Get all methods of this class
MethodgetDeclaredMethod(String name, Class<?>... parameterTypes)Gets any method specified by the class
public class person {

    public String name;
    private String id;
    public person() {
    }
    private person(String name) {
        this.name = name;
    }

    private String getName() {
        return name;
    }

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

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
-----------------------------------------------------------------------------
public class students extends person{

    public String name;
    private String id;
    public int age;
    static int score;
    public students() {
    }

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

    private students(String name, String id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "students{" +
                "name='" + name + '\'' +
                ", id='" + id + '\'' +
                ", age=" + age +
                '}';
    }
    private void ac(){
        
    }
}
@Test
public void reflect_getMethod() throws ClassNotFoundException, NoSuchMethodException {
    Class stu = Class.forName("com.reflect.students");
    // Method[] getMethods() Gets all public methods
    for (Method f:stu.getMethods()) {
        System.out.println(f);
    }
    System.out.println("------------");
    //Method getMethod (String name, Class<?>... parameterTypes) Gets a single specified public method
    System.out.println(stu.getMethod("getName"));

    System.out.println("------------");
    // Method[] getDeclaredMethods() Gets all methods
    for (Method f:stu.getDeclaredMethods() ) {
        System.out.println(f);
    }
    System.out.println("------------");
    // Method getDeclaredMethod (String name, Class<?>... parameterTypes) Gets a single specified method
    System.out.println(stu.getDeclaredMethod("ac"));

}
//------->Output
public java.lang.String com.reflect.students.toString()
public java.lang.String com.reflect.students.getName()
public java.lang.String com.reflect.students.getId()
public int com.reflect.students.getAge()
    //Parent person
public void com.reflect.person.setName(java.lang.String)
public void com.reflect.person.setId(java.lang.String)
    //object class
public final void java.lang.Object.wait() throws java.lang.InterruptedException
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 boolean java.lang.Object.equals(java.lang.Object)
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()
------------
public java.lang.String com.reflect.students.getName()
------------
public java.lang.String com.reflect.students.toString()
public java.lang.String com.reflect.students.getName()
public java.lang.String com.reflect.students.getId()
private void com.reflect.students.ac()
public int com.reflect.students.getAge()
------------
private void com.reflect.students.ac()

2.Constructot class

Create instance objects through the newInstance method in the Constructot class

@Test
public void getnewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class<?> stu = Class.forName("com.reflect.students");
    // Gets all constructors, and each constructor is a Constructor object
    Constructor[] constructors = stu.getConstructors();
    Constructor<?> declaredConstructor = stu.getDeclaredConstructor();
    System.out.println(constructors[0].getClass().getName());

    /*
            Get an instance of the parameterless constructor at jdk1.9 was discarded
            Instead, getDeclaredConstructor().newInstance(),
            Get the corresponding constructor object and create an instance, then get the parameterless constructor without parameters
            Every creation has a new instance object
        */
    students o = (students) stu.newInstance();
    students o1 = (students) stu.getDeclaredConstructor().newInstance();
    System.out.println(o == o1);//false

}

Constructot class can also get the constructor's parameter type, number of parameters, annotations, modifiers and so on, which are not described here, mainly the instantiation of the object

3.Field class

Assigning values to fields

@Test
public void getfield() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
    Class<?> stu = Class.forName("com.reflect.students");
	//Create instance objects from parameterless constructors
    students o = (students) stu.getDeclaredConstructor().newInstance();
    //Get the name field
    Field field1 = stu.getField("name");
    System.out.println( " " + field1);
    //Call set assignment
    field1.set(o,"ss");
    Object o1 = field1.get(o);
    String name = o.getName();
    System.out.println(o1 + " " + name);
}

4.Method Class

Call Method

@Test
public void getMethod() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
    Class<?> stu = Class.forName("com.reflect.students");

    students o = (students) stu.getDeclaredConstructor().newInstance();
    Method setAge = stu.getMethod("setAge", int.class);
    //Call invoke to run setAge method, passing in object and specified parameter
    setAge.invoke(o,10);

    System.out.println(o.getAge());

}

There are also a series of methods in the Method class to get method modifiers, parameters, return types, and so on.

setAccessible

For private or default decorated methods and member variables, the calling method and the value of the query variable cannot be modified by default

Access by modifying permissions through setAccessible

@Test
public void setA() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException, InstantiationException, IllegalAccessException {
    Class<?> stu = Class.forName("com.reflect.students");

    students o = (students) stu.getDeclaredConstructor().newInstance();
    Field id = stu.getDeclaredField("id");

    id.setAccessible(true);
    id.set(o,"sss");

    System.out.println(id.get(o));
}

Method is used the same way

Keywords: Java

Added by simona_85 on Fri, 18 Feb 2022 21:51:27 +0200