Reflection is an advanced feature of Java that is used extensively in various open source frameworks.

** Open source frameworks often use the same set of algorithms to deal with different data structures. ** For example, with Spring’s dependency injection, we don’t need to create new objects ourselves. Spring does that.

However, if we want to new an object, we have to write it in code. But Spring can’t guess the name of our class. How does Spring get the object out of new?

That’s what reflection is all about.

The meaning and function of reflection

Java has two ways of manipulating classes: non-reflective and reflective.

Let’s start with the first one, non-reflection.

** non-reflective, which means statically manipulating classes according to code. ** For example, the following code:

Public class Application {public static void main(String[] args) {// Create a user object ClientUser client = new ClientUser(); }}Copy the code

The main() method is as simple as creating a user object. The whole process works like this: before the JVM runs, you have to figure out what objects to create, write them in code, and then you run the main() method, and the JVM creates a user object for you.

In simple terms, you write code, throw it to the JVM, run it, and it’s gone.

In this case, the programmer must control everything, and what objects to create must be written in advance in the code. For example, if I wanted to create one more merchant object, I would have to change the code:

Public class Application {public static void main(String[] args) {// Create a user object ClientUser client = new ClientUser(); // Create a merchant object ShopUser shop = new ShopUser(); // omit numerous new operations}}Copy the code

In this way, programmers have to change the code whenever the requirements change, which is inefficient. For example, if you have a more complex project, you have to create not only objects, but also set member variables. So every time you add a new object, you have to change a bunch of code, and sooner or later you’re dead.

Can these tasks be simplified?

This uses the second way of manipulating classes, reflection. Reflection is a mechanism for dynamically manipulating classes. ** For example, if I want to create a bunch of objects, instead of writing them down in code, I put them in a configuration file or database, and when the program runs, I read the configuration file to create the objects.

Again, the code above, modified by reflection, looks like this:

Public class Application {private static Set<String> configs = new HashSet<>(); static { configs.add("com.jiarupc.reflection.ShopUser"); configs.add("com.jiarupc.reflection.ClientUser"); Public static void main(String[] args) throws Exception {// Read the configuration file for (String config: Clazz = class.forname (config); Object = clazz.newinstance (); System.out.println(object); }}}Copy the code

When you run the main() method, the program reads the configuration file and creates objects from the configuration file. Have you noticed how much easier it is to work with reflex? Once we add a new object, we just add one line of configuration file and leave it alone.

Does this remind you of some open source framework? For example, Spring’s dependency injection.

@service public class UserService {// Omit the business code... }Copy the code

You add a line of annotations to a class (which is equivalent to adding a line of configuration), Spring takes over the class for you, and you don’t have to worry about creating objects. Spring can take over your class because it takes advantage of Java’s reflection.

In short, if we use reflection well, we can reduce a lot of repetitive code.

Next, let’s see what reflection can do

Reflection gets class information

If you want to manipulate a class, you need to know about that class. For example, what variables, what constructors, what methods… Without that information, you can’t even write code, let alone reflect.

We’ll focus on how to get Class objects, member variables, and methods.

Class objects can only be created by the JVM and contain all the information about a Class, including member variables, methods, constructors, and so on.

In other words, creating Class objects is a MATTER for the JVM, not ours. To manipulate a Class by reflection, you need to get the Class object. There are three ways to do this:

1. Class.forname (" fully qualified name of the Class ") 2. The name of the class. The classCopy the code

You can look at the following code:

Public class User {public static void main(String[] args) throws Exception {// 1.class.forName (" fully qualified name of the class ") class clazz1  = Class.forName("com.jiarupc.reflection.User"); GetClass () User User = new User(); Class clazz2 = user.getClass(); Class class clazz3 = clientuser.class; }}Copy the code

Once you’ve got the Class object in these three ways, you can use reflection to get information about the Class.

The **Field object represents a member variable of the class. ** We want to get a Class member variable that can call the Class object’s four methods.

Field[] getFields() - Obtain all public fields. 3. Field getDeclaredField(String name) - obtain all public fields 4. Field[] getDeclaredFields() - Retrieves all member variablesCopy the code

GetDeclaredFields () = getDeclaredFields(); getDeclaredFields() = getDeclaredFields(); getDeclaredFields() = getDeclaredFields();

Public class User {// private Long ID; Private String username; Public static void main(String[] args) throws Exception {// Obtain the Class object Class clazz = Class.forName("com.jiarupc.reflection.User"); Field[] fields = clazz.getDeclaredFields(); For (Field Field: fields) {String MSG = string. format(" variable name: %s, type: %s", field.getName(), field.getType()); System.out.println(msg); }}}Copy the code

The **Method object represents the Method of the class. ** To get a method of a Class, the Class object also provides four methods:

1. Method getMethod(String name, Class[] params) 3. Method getDeclaredMethod(String name, Class[] params) 4. Method[] getDeclaredMethods() - Get all methodsCopy the code

Similarly, we try to get all the methods, first using the fully qualified name of the User Class to get the Class object, then calling getDeclaredMethods() to get all the member methods of the User Class, and finally printing the method name and parameter number to the console.

Public class User {// private Long ID; Private String username; Public static void main(String[] args) throws Exception {// Obtain the Class object Class clazz = Class.forName("com.jiarupc.reflection.User"); [] methods = clazz.getDeclaredmethods (); for (Method method : {String MSG = string. format(" method name: %s, parameter number: %s", method.getName(), method.getParameterCount()); System.out.println(msg); }}}Copy the code

Seeing this, you should know how to get information about a class through reflection.

First, there are three ways to get the Class object of a Class; Next, we get the class’s member variables, which correspond to the Field object; Finally, get the Method of the class, which corresponds to the Method object.

Reflection, however, can not only retrieve information about classes, but also manipulate them.

Reflection operation class

Reflection can do a lot of things, but I think the most important ones are: create objects and call methods.

Creating objects is the prerequisite for everything. For reflection, if there is no object created, we can only look at the information of the class. You know, what member variables are there, what methods are there, things like that. If you want to manipulate a class, the first step is to create an object.

To create an object, you must call the constructor of the class. ** This can be done in two ways. The simplest is: if you write a class without a constructor, the class will have a constructor with no arguments.

Public class User {// private Long ID; Private String username; Public static void main(String[] args) throws Exception {// Obtain the Class object Class clazz = Class.forName("com.jiarupc.reflection.User"); Object = clazz.newinstance (); System.out.println(object); }}Copy the code

We first get the Class object of the Class and then call newInstance().

But there’s another case where I don’t use Java’s built-in constructor and write it myself. This is a bit more complicated. You have to specify the type of the argument to be passed in, get the constructor, and then call newInstance().

Public class User {// private Long ID; Private String username; Constructor 1 public User(Long id) {this.id = id; this.username = null; } public User(Long id, String username) {this.id = id; this.username = username; } public static void main(String[] args) throws Exception {// Obtain the Class object clazz = Class.forName("com.jiarupc.reflection.User"); Constructor = clazz.getconstructor (Long. Class, string.class); // Constructor = clazz.getconstructor (Long. Object object = constructor.newInstance(1L, "jiarupc"); System.out.println(object); }}Copy the code

We need to set the id and username from the start, so you need to pass in the type of the argument. Find the 2-constructor; You then pass the ID and username to the constructor.newinstance () method to get a user object.

Once the constructor is in hand and the object is created, we can call the object’s methods.

The method of calling an object is divided into two steps: first, find the method; The second step is to invoke the method. That sounds pretty simple, and it’s actually pretty simple. You can look at the code below.

Public class User {// private Long ID; Private String username; / /.. Set /get method ignored public static void main(String[] args) throws Exception {// Obtain the Class object Class clazz = Class.forName("com.jiarupc.reflection.User"); Object = clazz.newinstance (); System.out.println(object); -setUsername Method Method = clazz.getMethod("setUsername", string.class); // Invoke the setUsername() method of object. Invoke (object, "JerryWu"); Field[] fields = clazz.getDeclaredFields(); For (Field Field: fields) {String MSG = string. format(" variable name: %s, variable value: %s", field.getName(), field.get(object)); System.out.println(msg); }}}Copy the code

The setUsername method is named -setusername and the parameter type is -string. Then, pass the -username argument to method.invoke() and execute the setUsername method; Finally, verify the results by printing out all the member variables.

Write in the last

Reflection, a mechanism for dynamically manipulating classes, serves two purposes.

First, reflection allows us to retrieve information about a class, including: member variables, methods, constructors, and so on.

Second, reflection allows us to manipulate a class by creating an object, calling its methods, and modifying its member variables.

Because the framework has to use the same set of algorithms to deal with different data structures. So, open source frameworks make a lot of use of reflection. Spring’s dependency injection, for example, relies on reflection.