Java reflection of Java notes

Keywords: Java jvm less

Java reflection actually means that in the running state, we can know the methods and properties of any class. For any object, we can call its methods and properties. We call this function of dynamically obtaining object information and calling object methods reflection mechanism.

Class Class

① Java is a class (including this interface) except for the basic type
② The data type of class/interface is Class
③ Every time a class is loaded, the JVM creates an instance of class type for it

public final class Class{
	private Class(){...}
	//Note that it is private. Our own program cannot create a Class instance
}

④ A class instance contains the complete information of a class
⑤ Getting the class information through the class instance is called reflect ion
⑥ Class instances are unique in the JVM. You can use = = as a comparison, but this comparison is accurate and different from the traceable parent class comparison of instanceof

How to get a class instance of a class
Class cls1 = String.class;//Type.class     

String s = "Hello";
Class cls2 = s.getclass();//getclass method (less used)

Class cls3 = Class.forname("java.lang.String");//Class. Forname method {much used)
boolean cls1 == cls2//ture
boolean cls2 == cls3//ture
Class cls = String.class;
String s = (String)cls.newInstance();
//We can use the newInstance method to create a new instance without parameters

Access field

① Field getField(name): get the field of a public (including the parent class) according to the field name
② Field getDeclaredField(name): get a field of the current class by the field name (excluding the parent class)
③ Field[] getFields(): get all public fields (including the parent class)
④ Field[] getDeclaredFields(): get all fields of the current class (excluding the parent class)

class Person {
    public String name;
}
class Student extends Person {
    public int score;
    private int grade;
}
public class Main {
    public static void main(String[] args) throws Exception {
        Class stdClass = Student.class;
        // Get the public field "score":
        System.out.println(stdClass.getField("score"));
        // Get the inherited public field "name":
        System.out.println(stdClass.getField("name"));
        // Get private field "grade":
        System.out.println(stdClass.getDeclaredField("grade"));
    }
}

Get and set the value of field

Using reflection to get a Field instance of a Field is only the first step. We can also get the value of the Field corresponding to an instance.

Integer n = new Integer(123);
Class cls = n.getclass();
Feild f = cls.getDeclaredFeild("value");
//get for value and set for value
 f.get(n);//123 these two sentences are equivalent to n.value
 f.set(n,456);//n becomes 456


Note that this code is actually problematic. value must be defined in private
 So we need to make a statement before get():
Calling Field.setAccessible(true) means that access is allowed regardless of whether the field is public or not

Calling method

①Method getMethod(name, Class… ): get the method of a public (including the parent class)
②Method getDeclaredMethod(name, Class… ): get a method of the current class (excluding the parent class)
③ Method[] getMethods(): get methods of all public (including parent class)
④ Method[] getDeclaredMethods(): get all methods of the current class (excluding the parent class)

class Person {
    public String getName() {
        return "Person";
    }
}
class Student extends Person {
    public int getScore(String type) {
        return 100;
    }
    private int getGrade(int year) {
        return 1;
    }
}
public class Main {
    public static void main(String[] args) throws Exception {
        Class stdClass = Student.class;
        // Get the public method getScore. The parameter is String:
        System.out.println(stdClass.getMethod("getScore", String.class));
        // Get the inherited public method getName, no parameters:
        System.out.println(stdClass.getMethod("getName"));
        // Get the private method getGrade with the parameter int:
        System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
    }
}
Invoke
public class Main {
    public static void main(String[] args) throws Exception {
        String s = "Hello world";
        Method m = String.class.getMethod("substring", int.class);
        //Call this method on the s object
        String r = (String) m.invoke(s, 6);
        //Calling invoke on a Method instance is equivalent to calling the Method
        //The first parameter to invoke is the object instance
        //In which instance the method is called, the following variable parameters should be consistent with the method parameters, otherwise an error will be reported
        //For example, s here is the instance object to execute the method, and 6 is the Integer parameter in the method
        System.out.println(r);
    }
}
If the Method obtained represents a static Method
 When calling a static method, you do not need to specify an instance object
 So the first parameter passed in by the invoke method is always null

polymorphic

When a method is called by reflection, the same principle of polymorphism is followed: that is, the overriding method of the actual type is always called, if any.
So

Method m = Person.class.getMethod("hello");
m.invoke(new Student());

In fact, it is equivalent to:

Person p = new Student();
p.hello();

Call constructor

As mentioned earlier, we can create an instance through newInstance, but there are limitations in calling Class.newInstance(), which can only call the public parameterless constructor of the class. If the constructor has parameters or is not public, it cannot be called directly through Class.newInstance().
In order to call any constructor, the reflection API of Java provides the constructor object, which contains all the information of a constructor and can create an instance. Constructor object is very similar to Method, except that it is a constructor, and the call result always returns the instance:

public class Main {
    public static void main(String[] args) throws Exception {
        // Get the constructor Integer(int):
        Constructor cons1 = Integer.class.getConstructor(int.class);
        // Call construction method:
        Integer n1 = (Integer) cons1.newInstance(123);
        // Get the constructor Integer(String)
        Constructor cons2 = Integer.class.getConstructor(String.class);
        Integer n2 = (Integer) cons2.newInstance("456");
    }
}
The method of obtaining Constructor by Class instance
getConstructor(Class): gets the Constructor of a public;
getDeclaredConstructor(Class): get a certain Constructor;
getConstructors(): get the constructors of all public;
getDeclaredConstructors(): get all constructors.

Note that Constructor is always the construction method defined by the current class, which has nothing to do with the parent class, so there is no polymorphism problem. When a non public Constructor is called, access must be allowed first through the setAccessible(true) setting.

Get inheritance relationship

Get parent class
As mentioned earlier, we can get a class instance in three different ways, so how to get the class instance of their parent class.

public class Main {
    public static void main(String[] args) throws Exception {
        Class i = Integer.class;
        Class n = i.getSuperclass();//Get its parent class
        }
}
//Any Class other than Object that is not interface must have a parent Class type.

Get interface
Because a Class may implement one or more interfaces, we can query the implemented interface types through Class. For example, query the interface implemented by Integer:

public class Main {
    public static void main(String[] args) throws Exception {
        Class s = Integer.class;
        Class[] is = s.getInterfaces();
        //Traverse and print out all its interfaces
        for (Class i : is) {
            System.out.println(i);
        //After running, the following interfaces are available for the Sieger
        //java.lang.Comparable
	//java.lang.constant.Constable
	//java.lang.constant.ConstantDesc
        }
    }
}

① getInterfaces() only returns the interface type directly implemented by the current class, excluding the interface type implemented by its parent class
② Calling getSuperclass() on the Class of all interfaces returns null, and getInterfaces() is used to get the parent interface of the interface
③ If a class does not implement any interface s, getInterfaces() returns an empty array.
Inheritance relationship
When we judge whether an instance is of a certain type, we normally use the instanceof operator:

Object n = new Integer(123);
boolean isDouble = n instanceof Double; // false
boolean isInteger = n instanceof Integer; // true
boolean isNumber = n instanceof Number; // true

If there are two Class instances, you can call isAssignableFrom() to determine whether an upward transformation is valid:

Integer.class.isAssignableFrom(Integer.class); // true, because Integer can be assigned to Integer
Number.class.isAssignableFrom(Integer.class); // true, because Integer can be assigned to Number
Object.class.isAssignableFrom(Integer.class); // true, because Integer can be assigned to Object
Integer.class.isAssignableFrom(Number.class); // false, because Number cannot be assigned to Integer

In short, judge whether the type after isAssignable From can be assigned to the former (that is, whether the latter is a subclass of the former)

Published 57 original articles, won praise 5, visited 1756
Private letter follow

Posted by bastienvans on Thu, 05 Mar 2020 04:20:16 -0800