Xiao Li is not bald

1. The reflection

Java has compile time and run time

Compilation method description:

  1. Static compilation: Type & bind objects are determined at compile time. As common usenewKeyword to create an object
  2. Dynamic compilation: Determine type & bind object at run time. Dynamic compilation showsJavaFlexibility, polymorphic properties & reduce coupling between classes

Let’s go into today’s lesson with the following questions

  • What is reflection?
  • What is the function of reflection?
  • What are the advantages of reflection? What are the disadvantages?

1.1 What is Reflection

Reflection is a Feature of Java that allows a running Java program to retrieve information about itself and manipulate the internal properties of a class or object.

Oracle’s official explanation for reflection is:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.

The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

With reflection, we can get members and member information for each type in the assembly at run time. The type of object we normally create with new is determined at compile time. Java reflection, on the other hand, creates objects dynamically and calls their properties, the type of which is unknown at compile time. So we can create objects through reflection, even if the type of the object is unknown at compile time.

The core of reflection is that the JVM dynamically loads classes, calls methods, and accesses properties at run time; it doesn’t need to know who the object is running on at compile time.

Java reflection provides the following functions:

  • Determine the class to which any object belongs at run time
  • Constructs an object of any class at run time
  • Determine which member variables and methods any class has at run time
  • Call a method of any object at run time

We can fetch “any” class, object, variable, method, etc you want at run time.

Note: Reflection is operated at run time, not compile time.

1.2 Main uses of reflection

  • Implement design patterns such as factory pattern and agent pattern.
  • JDBC database connection.
  • Spring, Struts, and other frameworks use reflection to dynamically load objects at run time.
  • IDE development tooltips, such as when we enter an object or class and want to call its properties or methods, press the dot and the compiler automatically lists its properties or methods.

1.3 Advantages and disadvantages of reflection

Advantages:

  • Types can be determined at run time, dynamic class loading, and other operations.
  • Improve the flexibility of your code. For example, JDBC can dynamically connect to a database.

Disadvantages:

  • Performance issues

    Because reflection includes some dynamic types, the JVM cannot optimize this code. Therefore, reflection operations are much slower than direct calls. So try to avoid using reflection in code that is frequently executed or in programs that require high performance.

    (Reflection is about 50-100 times slower than a direct call, but it takes a million times to feel it.)

  • Security restrictions

    Using reflection requires that the program be run in an environment with no security restrictions.

  • Inside the ferrous

    Reflection allows code to do things that are not normally allowed (accessing private properties or methods), so using reflection can have the unintended side effect of making code functional errors and reducing portability. Reflection breaks the abstraction of the code, so when the platform changes, the behavior of the code may change with it.

Question: Java reflection can access and modify private member variables, so does encapsulation private make sense?

Since thieves can access and remove private members’ furniture, does it make sense to encapsulate it as a security door? This is the same reason, and Java from the application layer provides us with the security management mechanism, the security manager, each Java application can have its own security manager, it will be in the running stage check need to protect the resource access and other provisions of the operating rights, protect the system against malicious attacks operation, to achieve the system’s security policy.

So reflection actually has internal security controls when it is used, and if the security Settings forbid these, then reflection cannot access private members.

1.4 Usage

1.4.1 Class

Class holds runtime information of the corresponding type. While the Java program is running, the Java virtual machine maintains a java.lang.Class object for all types. This Class object holds all runtime information about the object.

1.4.1.1 for Class

So how do we get the Class we want, look this Code

    public static void main(String[] args) {
        // Method 1: object.getClass ()
        The getClass() method of the Object Class returns an instance of the Class
        String name = "Not a bald little Lee programmer."; Class<? > classType = name.getClass(); System.out.println("Object.getClass() classType: " + classType);

        // Method 2: t.class
        // T is any Java typeClass<? > classType2 = String.class; System.out.println("T.Class classType: " + classType2);

        // Method 3: class.forname
        try{ Class<? > classType3 = Class.forName("java.lang.String");
            System.out.println("Class.forName classType: " + classType2);
            ClassNotFoundException is thrown if className is not found
        } catch(ClassNotFoundException e) { e.printStackTrace(); }}Copy the code

Three ways to get a Class

  • getClass()
  • T.class
  • Class.forName

These three usages need to be used flexibly in specific scenarios, such as JDBC to obtain the database type of connection through class.forname (” classpath “).

1.4.1.2 Obtaining the Parent Class

Get the Class of the parent Class using the getSuperclass() method as shown in the following example:

Class<? > superclass = Integer.class.getSuperclass(); System.out.println(superclass); System.out.println(superclass.getSuperclass()); System.out.println(superclass.getSuperclass().getSuperclass()); System.out.println(superclass.getSuperclass().getSuperclass().getSuperclass());Copy the code

The results

class java.lang.Number
class java.lang.Object
null
Exception in thread "main" java.lang.NullPointerException
Copy the code

The parent class of Integer is Number. The parent class of Number is Object. Object has no parent class.

1.4.1.3 summary

Once you get the desired Class, you can get all of its information.

Before you get the information you want, you might as well know the knowledge.

Distinction between “Declared” and “Declared” in methods

  1. Methods without “Declared” support extraction of fields, methods, and constructors including inheritance and public.
  2. Methods with “Declared” support fetching fields, methods, and constructors that include all constructors (public and private, excluding inheritance) of the current class.

1.4.2 Field

1.4.2.1 access Field

How to get field information from a Class instance. The Class Class provides the following methods to get fields:

  • Field getField(String name) : Gets a public Field based on the Field name
  • Field[] getFields() : Gets all public fields
  • Field getDeclaredField(String name) : Obtains a Field of the current class based on the Field name
  • Field[] getDeclaredFields() : Gets all fields of the current class

Quick, quick, show me code

public class FiledTest1 {
    public static void main(String[] args) throws NoSuchFieldException {
        Class stdClass = Student.class;
        // Get public field "score"
        System.out.println(stdClass.getField("score"));
        // Get the continuation of the public field "name"
        System.out.println(stdClass.getField("name"));
        // select grade from private;
        System.out.println(stdClass.getDeclaredField("grade")); }}class Student extends Person{
    public int score;
    private int grade;
}

class Person{
    public String name;
}
Copy the code

Running results:

public int com.javastudy.reflection.Fields.Student.score
public java.lang.String com.javastudy.reflection.Fields.Person.name
private int com.javastudy.reflection.Fields.Student.grade
Copy the code

1.4.2.2 Obtaining Field information

A Filed object contains all information about a field:

  • GetName () : Returns the field name, for example, name;
  • GetType () : Returns the field type, which is also an instance of Class, for example, string.class
  • GetModifiers () : Return field modifiers. This is an int, and different bits mean different things.

The java.lang.reflect.Method.getModifiers() method returns the Java language modifiers for the method represented by this Method object, as an integer. The Modifier class should be used to decode the modifiers.

The getModifiers () method returns Java language modifiers, as integers, for the methods represented by the method object. Modifier classes should be used to decode modifiers.

public class FieldTest2 {

    private final String name = "Not a bald little Lee programmer.";

    public static void main(String[] args) throws NoSuchFieldException {
        Class c = FieldTest2.class;
        Field field = c.getDeclaredField("name");
        int mod = field.getModifiers();
        System.out.println("name: " + field.getName());
        System.out.println("type: " + field.getType());
        System.out.println("final: " + Modifier.isFinal(mod));
        System.out.println("public: " + Modifier.isPublic(mod));
        System.out.println("protected: " + Modifier.isProtected(mod));
        System.out.println("private: " + Modifier.isPrivate(mod));
        System.out.println("static: "+ Modifier.isStatic(mod)); }}Copy the code

Running results:

name: name
type: class java.lang.String
final: true
public: false
protected: false
private: true
static: false
Copy the code

1.4.2.3 Obtaining Field Values

We’ve got the Field, and we need to get the value of that Field. Let’s use the above example to get the name value.

public class FieldTest3 {

    private final String name = "Not a bald little Lee programmer.";

    public static void main(String[] args) throws Exception {
        Object object = new FieldTest3();
        Class c = FieldTest3.class;
        Field field = c.getDeclaredField("name"); Object value = field.get(object); System.out.println(value); }}Copy the code

Running results:

Not some bald little Li programmerCopy the code

We get the Field value by getting (), so let’s look at the following example:

public class FieldTest4 {

    public static void main(String[] args) throws Exception { 
        Object animal = new Animal("Not bald little Li programmer Animal111");
        Class c = Animal.class;
        Field field = c.getDeclaredField("name");
        Object value = field.get(animal);
        System.out.println(value);
// Animal animal = new Animal();
// animal.testFiled();}}class Animal {
    private String name;

    public Animal(a) {}public Animal(String name){
        this.name = name;
    }

    public void testFiled(a) throws Exception {
        Object animal = new Animal("Not bald little Li programmer Animal222");
        Class c = Animal.class;
        Field field = c.getDeclaredField("name"); Object value = field.get(animal); System.out.println(value); }}Copy the code

Running results:

Exception in thread "main" java.lang.IllegalAccessException: Class com.javastudy.reflection.Fields.FieldTest4 can not access a member of class com.javastudy.reflection.Fields.Animal  with modifiers "private"Copy the code

WTF? Unexpectedly abnormal, xiao Li you are playing me, the first time can, the second time and prompt no permission, in the end can get the value I want. Of course I can. I’ll show you if I can’t.

All we need to do is add the following code to the filed. Get () step. It doesn’t matter if you’re public or private.

field.setAccessible(true);

Copy the code

So let’s think about why we can access the code the first time without adding it.

You have a nose and two ears. They are private to you. You can touch them and pick them, but when people want to touch them, they have to get your permission (setAccessible(true)). So if you look at the code that we just did, you get the idea. If you don’t understand, open the two comments above:

Animal animal = new Animal();
animal.testFiled();

Copy the code

Running results:

Not bald little Li programmer 222Copy the code

1.4.2.4 Setting Field Values

The Field instance can be used to get and set the Field value of the specified instance.

Setting Field values is done through the set method of Field.

// The first argument is the specified instance
// The second argument is the value to be modified
void set(Object obj, Object value)

Copy the code

Example code is as follows:

public class FieldTest5 {
    public static void main(String[] args) throws Exception {
        Teacher teacher = new Teacher("Not a bald little Lee programmer.");
        Class c = teacher.getClass();
        Field field = c.getDeclaredField("name");
        field.setAccessible(true);
        field.set(teacher,"Xiao Li is not bald."); System.out.println(field.get(teacher)); }}class Teacher{
    private String name;

    public Teacher(String name){
        this.name = name;
    }

    public String getName(a) {
        returnname; }}Copy the code

Print result:

Xiao Li is not baldCopy the code

In order not to be bald, I am easy. So it’s time to ask questions

What is the role of Field in the obj arguments to get and set?

NullException is returned if the obj parameter is null. If the obj parameter is not null, NullException will be returned.

1.4.2.5 summary

Java’s reflection API provides a Field class that encapsulates all information about a Field:

  • GetField (String name), getFields(), getDeclaredField(), getDeclaredFields()
  • Methods to get Field information from Field instances: getName(), getType(), getModifiers()
  • Field instances can be used to read or set fields of an object. If access is restricted, setAccessible(true) is called first, and then non-public fields are accessed.

1.4.3 Method

1.4.3.1 access Method

The Class Class provides the following methods to get information about all methods:

  • Method getMethod(String name, Class<? >… ParameterTypes: Gets a public Method based on the Method name and parameter type

  • Method[] getMethods() : Get all public methods

  • Method getDeclaredMethod(String name, Class<? >… ParameterTypes: Gets a Method of the current class based on the Method name and parameters

  • Method[] getDeclaredMethods() : Gets all methods of the current class

Take a look at the sample code:

public class MethodTest1 {
    public static void main(String[] args) throws Exception{
        Class c = Student.class;
        Public getScore (String);
        System.out.println(c.getMethod("getScore",String.class));
        // Get the inherited public method getName, no arguments;
        System.out.println(c.getMethod("getName"));
        // Get the private method getGrade, int;
        System.out.println(c.getDeclaredMethod("getGrade".int.class)); }}Copy the code

Running results:

public int com.javastudy.reflection.Methods.Student.getScore(java.lang.String)
public java.lang.String com.javastudy.reflection.Methods.Person.getName()
private int com.javastudy.reflection.Methods.Student.getGrade(int)
Copy the code

1.4.3.2 Obtaining Method Information

A Method object contains all the information about a Method:

  • GetName () : Returns the method name, for example, “getScore”
  • GetReturnType () : Returns the return value type of the method. It is an instance of Class, for example, “string.class”.
  • GetParameterTypes () : Returns the parameter type of the method, which is a Class array, e.g. {string.class, int.class}
  • GetModifiers () : Return method modifiers, similar to Field getModifiers()

The following is an example:

public class MethodTest2 {
    public static void main(String[] args) throws Exception{
        Class c = Student.class;
        Method method= c.getDeclaredMethod("getGrade".int.class);

        System.out.println("name : " + method.getName());
        System.out.println("returnType : "+ method.getReturnType()); Class<? >[] parameterTypes = method.getParameterTypes(); System.out.println("Length of paramaterTypes:" + parameterTypes.length);
        for (Class parameterType : parameterTypes){
            System.out.println("paramaterTypes : "+ parameterType); }}}Copy the code

Running results:

name : getGrade
returnType : intThe length of paramaterTypes:1
paramaterTypes : int
Copy the code

1.4.3.3 Calling a method

Calling normal methods

Take a look at an example:

public class MethodTest3 {
    public static void main(String[] args) throws Exception {
        String s = "Not a bald little Lee programmer.";
        Method method = String.class.getMethod("substring".int.class);
        Method method2 = String.class.getMethod("substring".int.class, int.class);
        String result = (String) method.invoke(s,7);
        String result2 = (String) method2.invoke(s,1.9); System.out.println(result); System.out.println(result2); }} Result: programmer is bald little li programCopy the code

Analyze the programmer Xiao Li is how bald:

  1. Method is obtained by using the getMethod Method Method of the Class instance. Different methods are obtained depending on the name and parameter of getMethod.
  2. Using Method’s invoke Method is equivalent to calling that Method. The first argument to invoke is an object instance, followed by variable arguments that match the method arguments, otherwise an error is reported.
Calling static methods

To invoke a static method, you do not need to specify an instance object. The invoke method is always passed a null or null value as its first argument.

public class MethodTest4 {
    public static void main(String[] args) throws Exception{
        // Get integer.parseint (Stirng) with String
        Method method = Integer.class.getMethod("parseInt", String.class);
        // Call the static method to get the result
        // Integer result = (Integer)method.invoke("", "12345");
        Integer result = (Integer)method.invoke(null."12345"); System.out.println(result); }} Run result:12345
Copy the code
Call non-public methods

For non-public methods, we can get class.getDeclaredMethod (), but the call throws an IllegalAccessException. To call a non-public Method, allow it to be called with method.setaccessible (true) :

public class MethodTest5 {
    public static void main(String[] args) throws Exception{
        Person p = new Person();
        Method method = p.getClass().getDeclaredMethod("setName", String.class);
        method.setAccessible(true);
        method.invoke(p,"Not a bald little Lee programmer."); System.out.println(p.name); }}Copy the code

In addition, setAccessible(true) may fail. If the JVM runtime has a SecurityManager, it checks against the rule, potentially blocking setAccessible(true). For example, a SecurityManager may not allow setAccessible(true) calls to classes of Java and Javax-starting packages to keep the JVM core libraries safe.

1.4.3.4 polymorphism

If a Person defines a hello() Method and its subclass Student overrides it, what Method is called when we get the Method from Person.class on the Student instance?

public class MethodTest6 {
    public static void main(String[] args) throws Exception{
        // Get the Hello method of Person
        Method method = Person.class.getMethod("hello");
        // Call hello on the Student instance
        method.invoke(newStudent()); }}public class Person {
    public void hello(a){
        System.out.println("Person:hello"); }}public class Student extends Person {
    public void hello(a){
        System.out.println("Student:hello"); }}Copy the code

1.4.3.5 Running Results

Student:hello
Copy the code

Student: Hello is printed out, so using reflection to call a method still follows the polymorphic principle: always call an override method of the actual type.

The reflection code above:

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

Is equivalent to:

Person p = new Student();
p.hello();
Copy the code

1.4.3.5 summary

Java’s reflection API provides a Method object that encapsulates all information about a Method:

  • GetMethod (), getMethods(), getDeclaredMethod(), getDeclaredMethods()
  • Methods to get field information from a Method instance: getName(), getReturnType(), getParameterTypes(), getModifiers()
  • Object invoke(Object instance, Object… parameters)
  • Access non-public methods by setting setAccessible(true)
  • When a method is called through reflection, it can still follow the principle of polymorphism

1.4.4 Constructor

1.4.4.1 get Constructor

To get all Constructor information from the Class instance, the Class Class provides the following methods to get the method:

  • Constructor getConstructor(Class<? >… ParameterTypes: Gets public Contructor based on parameters

  • Constructor<? >[] getConstructors() : Get all public Contructor

  • Constructor getDeclaredConstructor(Class<? >… ParameterTypes) : Gets Contructor of the current class based on the parameters

  • Constructor<? >[] getDeclaredConstructors() : Get all current classes of Contructor

Constructor is always the Constructor of the current class definition, independent of the parent class, so there is no problem with polymorphism.

The following is an example:

public class ContructorTest1 {
    public static void main(String[] args) throws Exception{
        Class c = Person.class;
        Person p = (Person) c.newInstance();

        Constructor cons1 = c.getConstructor(int.class);
        Person p1 = (Person)cons1.newInstance(30);

        Constructor cons2 = c.getDeclaredConstructor(String.class);
        cons2.setAccessible(true);
        Person p2 = (Person)cons2.newInstance("Not a bald little Lee programmer.");

        Constructor cons3 = c.getConstructor(String.class, int.class);
        Person p3 = (Person)cons3.newInstance("Not bald little Lee programmer. -35.".35); }}Copy the code
Person.class

public class Person {
    private String name;
    private int age;

    public Person(a) {
        System.out.println("Person");
    }

    public Person(int age) {
        this.age = age;
        System.out.println("Person age:" + age);
    }

    private Person(String name) {
        this.name = name;
        System.out.println("Person name:" + name);
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person toString:" + toString());
    }

    @Override
    public String toString(a) {
        return "Person{" +
                "name='" + name + '\' ' +
                ", age=" + age +
                '} '; }}Copy the code

Running results:

Person toString:Person{name='Not bald little Lee programmer -35', age=35}
Copy the code

1.4.4.2 summary

Based on the above results, the following conclusions can be drawn:

  1. The parameterless constructor is obtained through the Class instance’s newInstance()
  2. To get the argument Constructor, get the Constructor instance from the Class instance: getConstructor(), getConstructors(), getDeclaredConstructor(Class
    … The parameterTypes), getDeclaredConstructors ()
  3. NewInstance (Object… Parameters) creates an instance object
  4. Calling non-public Contructor requires setting setAccessible(true) to allow access, but may fail.

1.4.5 Interface

We can get all interfaces implemented by the current Class via Class getInterfaces(), as shown in the following example:

public class ReflectionInterfaceTest {
    public static void main(String[] args) {
        Class s = Integer.class;
        Class[] interfaces = s.getInterfaces();
        for(Class c:interfaces){ System.out.println(c); }}}Copy the code

Running results:

interface java.lang.Comparable

Copy the code

2. To summarize

From this article you have a general understanding of reflection, let’s review it again:

  • Reflection is a Java feature that allows you to dynamically retrieve objects by reflection.
  • Use of reflection: design patterns such as proxy mode; Connect to the database through JDBC; The Spring framework loads objects dynamically
  • Advantages of reflection: dynamic loading, improved code flexibility
  • Disadvantages of reflection: performance issues, security limitations, internal leaks
  • Use of reflection: By getting the Class instance, we can get all the information we want, including getting member variables, methods, and constructors, corresponding to Field, Method, and Constructor, respectively. You can get the information through the internal methods of these classes, for example, getName() to get the name.
  • If we modify or access a variable or method with private, we need to set method.setaccessible (true) before we can proceed.

In the next video I’m going to take you through reflection, and let’s take a closer look at it.

Reference 3.

Blog.csdn.net/carson_ho/a…

Zhidao.baidu.com/question/16…

www.liaoxuefeng.com/wiki/125259…