This is the 15th day of my participation in the August More Text Challenge. For details, see:August is more challenging

The meaning of reflection:

Some operations cannot be hardcoded and must be obtained at run time to be used

What reflection can do

Get all properties on obj, call all methods on obj, and call all constructors based on the specified class and the corresponding instance obj

Typical scenario

In the old version of Spring, 2.x, the mainstream was XML configuration. For example, in the following section, we configured an instance User of user.class. The Spring framework uses the text description in the class attribute. Load the User with class.forname (className) (or otherwise, and generate a User instance based on the configuration in the XML

<bean id="user" class="com.wb.bean.User">
</bean>
Copy the code

Work scene

Sometimes we need to write generic code, and it is not appropriate to hardcode the specified class directly, or the set of types cannot be handled by generics

For example, IF I need to generate a test class, I need to assign random values to its fields

Or, IF I need to copy an instance, if I hardcode something like B.setname (a.getname ()), I won’t be able to do that (and the code will look silly again)

Or maybe I have two sets of data templates that need to be mapped from instances of classA to instances of ClassB according to some rules (more on that later in this article)

Code demo

Let’s demonstrate the most common use of reflection in our work

@ToString
// The bean used in this demonstration
class User {
  String name;
  String job;
  User() {}
  private User(String name) {
    this.name = name;
  }
  private void sayHi(String prev) {
    System.out.printf("%s, I'm %s, %s is my job.", prev, name, job); }}// Use junit to test
@Test
public void f2(a) throws Exception {
  // Retrieve the type data of classClass<? > clz = User.class;// Class
       clz = Class.forName("com.wb.User"); // If our system loads a class file from another source after running, we can use the class path described in the text to load it. For example, this is how we loaded the mysql dirver when we first learned JDBC
  // Select the constructor based on the argument listConstructor<? > oneParams = clz.getDeclaredConstructor(String.class);// Settings can get private constructors
  oneParams.setAccessible(true);
  // Instantiate through the constructor
  Object obj = oneParams.newInstance("wangb");
  System.out.println(obj);  User(name=wangb, job=null, dept=null)
  // Retrieve the job field from the text description
  Field job = clz.getDeclaredField("job");
  // Set access to private properties
  job.setAccessible(true);
  // Perform the assignment operation
  job.set(obj, "touch-fish");
  System.out.println(obj);  User(name=wangb, job=touch-fish, dept=null)
  // Get the sayHi(String) method on CLZ
  Method sayHi = clz.getDeclaredMethod("sayHi", String.class);
  // The general setting is to get private methods
  sayHi.setAccessible(true);
  // Make the method call
  sayHi.invoke(obj, "morning"); // morning, I'm wangb, touch-fish is my job.
}
Copy the code

From the above test case, we get a strong feeling

We have a God-like view of what properties we can get, what methods we can use, and what constructors we can use, which didn’t exist when we were coding!

Details on

The reflectance-related classes we use are all located in java.lang.Reflect

Clz.getxxx is used to get properties, methods, and constructors. There are two options

  • Field name = clz.getDeclaredField(name);
  • Field name2 = clz.getField(name);

The former takes an extra step named. SetAccessible (true); You can access private fields, and then you can read and write names; For the latter, only public data can be obtained

Get all constructors

Constructor<? >[] constructors = clz.getConstructors();Copy the code

Get all methods

Method[] methods = clz.getDeclaredMethods();
Copy the code

Get all fields

Field[] fields = clz.getDeclaredFields();
Copy the code

When we need to get all the properties, we usually use a foreach loop to iterate

As shown below:

for (Field f : fields) {
  // do somethings
}
Copy the code

The last

Reflection is an advanced feature, but it’s not much of an API. The important thing is that once we understand what reflection can do, it’s not that hard, it’s just a matter of going around twice to get what we want, right

Of course, it should be noted that, after all, it is not a direct call. Reflection can cause performance problems. If you need to call frequently based on reflection, it is best to cache the relevant Fields and Methods to avoid the performance waste of repeated fetching