preface

Reflection is the soul of Java framework technology, learning reflection is very necessary, this article will be from the concept of entry, to practice, and then to explain the principle of reflection, I hope to help you.

Reflection to understand

The official resolution

Oracle’s official explanation for reflection is:

Reflection is commonly used by programs which require the ability to examine or
modify the runtime behavior of applications running in the Java virtual machine.
This is a relatively advanced feature and should be used only by developers who
have a strong grasp of the fundamentals of the language. With that caveat in
mind, reflection is a powerful technique and can enable applications to perform
operations which would otherwise be impossible.
Copy the code

Java’s reflection mechanism means that all properties and methods of any class can be known in the running state. And for any object, can call any of its methods; This ability to dynamically retrieve information and invoke object methods becomes the reflection mechanism of the Java language.

Vernacular understand

orthographic

Every Yin has a Yang, and every positive has an opposite. Since there is reflection, there must be orthotopic.

So what is orthophoto?

When we write code, when we need to use a class, we always know what that class does. Then we instantiate the class, and then we operate on the instantiated object, which is orthomorphism.

Student student = new Student();
student.doHomework("Mathematics");
Copy the code

reflection

Reflection is that we don’t know what class object we are initializing at first, and we can’t use the new keyword to create the object.

 Class clazz = Class.forName("reflection.Student");
 Method method = clazz.getMethod("doHomework", String.class);
 Constructor constructor = clazz.getConstructor();
 Object object = constructor.newInstance();
 method.invoke(object, "Chinese");
Copy the code

Orthophoto versus reflection

The above two pieces of code, the execution effect is the same, as shown in the figure

However, the implementation process is quite different:

  • The first piece of code already knows the class to run before it even runsStudent;
  • The second piece of code is to run the entire program from the stringreflection.Student, and know the class to operate onStudent.

conclusion

Reflection is when you know what class to operate on at run time, and you can get the complete construct of the class at run time and call the corresponding method.

Class Object Understanding

To understand Class objects, let’s take a look at RTTI. Run-time Type Identification (RTTI) is used to identify the Type and class information of an object at runtime.

How does Java allow us to recognize information about objects and classes at run time? There are two main approaches: one is traditional RRTI, which assumes that all types are known at compile time. The other is reflection, which allows us to discover and use information about a class at runtime.

Each Class has a Class object, which is generated each time a new Class is compiled (or, more properly, stored in a.class file of the same name). For example, if you create a Student Class, the JVM creates a Class object for the Student Class that holds the type information associated with the Student Class.

The object of the Class Class is to provide or obtain information about the type of an object at runtime

Basic use of reflection

Gets the Class object

There are three ways to get a Class object in reflection.

First, use the class.forname static method.

Class class1 = Class.forName("reflection.TestReflection");
Copy the code

Second, use the.class method of the class

Class class2 = TestReflection.class;
Copy the code

Third, use the getClass() method of the instance object.

TestReflection testReflection = new TestReflection();
Class class3 = testReflection.getClass();
Copy the code

Reflection creates objects, gets methods, member variables, constructors

This section covers the basic API uses of reflection, such as fetching methods, member variables, and so on.

Reflection creates objects

There are two main ways to create class objects through reflection:

Example code:

Class class1 = class.forname ("reflection.Student"); Student student = (Student) class1.newInstance(); System.out.println(student); Class = class1. GetConstructor (); Student student1 = (Student) constructor.newInstance(); System.out.println(student1);Copy the code

Running results:

Reflection gets the constructor of the class

Here’s an example:

Class class1 = Class.forName("reflection.Student");
Constructor[] constructors = class1.getDeclaredConstructors();
for (int i = 0; i < constructors.length; i++) {
    System.out.println(constructors[i]);
 }
Copy the code

Reflection gets the member variables of a class

Look at the demo:

Email public class student {private Integer age; public String email; } public class TestReflection { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class class1 = Class.forName("reflection.Student");
        Field email = class1.getField("email");
        System.out.println(email);
        Field age = class1.getField("age"); System.out.println(age); }}Copy the code

Running results:

getField(String name)
Not a public property

Reflection gets the method of the class

demo

public class Student {

    private void testPrivateMethod() {
        
    }
    public void testPublicMethod() {
        
    }
}

public class TestReflection {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class class1 = Class.forName("reflection.Student");

        Method[] methods = class1.getMethods();
        for(int i = 0; i < methods.length; i++) { System.out.println(methods[i]); }}}Copy the code

Running results:

How reflection works

From the previous section, we learned the basic API usage of reflection. Next, follow an example to learn the execution link of the reflection method.

public class TestReflection {
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("reflection.TestReflection");
        Method method = clazz.getMethod("target", String.class);
        method.invoke(null, "666"); } public static void target(String STR) {// Print stack information new Exception("#" +str).printStackTrace();
        System.out.println("invoke target method"); }}Copy the code

Stack information reflects the reflection call link:

java.lang.Exception: # 666
invoke target method
	at reflection.TestReflection.target(TestReflection.java:17)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at reflection.TestReflection.main(TestReflection.java:11)
Copy the code

The Invoke method executes a sequence diagram

Method invoke (); invoke ();

public Object invoke(Object obj, Object... The args) throws IllegalAccessException IllegalArgumentException, InvocationTargetException {/ / check permissionsif(! override) {if(! Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<? >caller = Reflection.getCallerClass();
            checkAccess(caller, clazz, obj, modifiers);
        }
    }
    MethodAccessor ma = methodAccessor;             // read volatile
    if(ma == null) { ma = acquireMethodAccessor(); // Get MethodAccessor} // return methodAccessor.invokereturn ma.invoke(obj, args);
}

Copy the code

Method’s invoke Method returns interface MethodAccessor. The MethodAccessor interface has three implementation classes. Which class invoke method is invoked?

If you enter the acquireMethodAccessor method, you can see that MethodAccessor is determined by the newMethodAccessor method of the ReflectionFactory.

Again into ReflectionFactory newMethodAccessor method, we can see the returned is DelegatingMethodAccessorImpl object, invoke method that is invoked is it.

Then look at DelegatingMethodAccessorImpl invoke method

DelegatingMethodAccessorImpl the invoke method returns the MethodAccessorImpl invoke method, and MethodAccessorImpl invoke method, Overridden by its subclass NativeMethodAccessorImpl, which returns the native method invoke0, as follows

Therefore, the invoke Method is determined by invoke0, the local Method, and the underlying c++ Method is relevant.

Some applications and problems of reflection

Reflex application

Reflection is the soul of Java framework technology, many frameworks use reflection technology, such as Spring, Mybatis, Hibernate and so on.

JDBC database connection

In JDBC database connection, generally including loading drivers, database connection and other steps. Loading the driver is to load the driver of the database through class.forname (), i.e. reflection technology, after introducing the relevant Jar package.

Use of the Spring framework

Spring loads beans through an XML configuration schema, another classic example of reflection.

Loading process:

  • Load the in-program XML configuration file into memory
  • The Java class parses the contents of the XML to get the relevant bytecode information
  • Use reflection to get an instance of Class
  • To dynamically configure instance properties, use

There are certainly advantages to this:

You don’t have to go to the new instance every time, and you can modify the configuration file, which is more flexible.

Problems with reflection

Performance issues

Java reflection does not perform well, mainly because the compiler is unable to optimize the reflection-related code. For those who are interested, check out this article Java – Reflection – Why-is-it-SO-slow

Security issues

We know that during the design of the singleton pattern, emphasis is placed on making the constructor private, because this prevents objects from being constructed from outside. Reflection, however, can take fields, methods, and constructors from a class and modify access. So it’s not necessarily safe.

Take an example of an instantiation using a private constructor via reflection.

public class Student {
    private String name;
    private Student(String name) {
        System.out.println("I'm a private constructor, I'm instantiated");
        this.name = name;
    }
    public void doHomework(String subject) {
        System.out.println("My name is." + name);
        System.out.println("I'm doing it."+subject+"Homework");
    }
}
public class TestReflection {
    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("reflection.Student"); / / to get private Constructor object Constructor Constructor = clazz. GetDeclaredConstructor (String. Class); //trueObjects indicating reflection should be used without Java language access checks. constructor.setAccessible(true);
        Student student = (Student) constructor.newInstance("jay@huaxiao");
        student.doHomework("Mathematics"); }}Copy the code

Running results:

Security restrictions

Reference and thanks

  • How reflection works
  • Get the private constructor by reflection and use it
  • Baymax: Java Reflection: Getting started, Using, and Working Principles
  • Design Mode Singleton Mode 6 (Anti-Reflection Attack)
  • Reflection: Application scenarios of the Java Reflection mechanism
  • In-depth understanding of Java type information (Class objects) and reflection mechanisms
  • Ideas for Java Programming

Personal public account

  • If you are a good boy who loves learning, you can follow my public account and study and discuss with me.
  • If you feel that this article is not correct, you can comment, you can also follow my public account, private chat me, we learn and progress together.