preface

Hi, my name is Jack Xu, and TODAY I’m going to talk to you about reflection in the core foundation, this thing called reflection that you say is important and important, it’s not important and it’s not important. The important thing is that when you look at the source code of some framework, which uses reflected code, you won’t be unreadable. It is not important because most of our daily work is in writing business code, the real operation class scene is very few. This, like English, will not affect your life, but when you move up the ladder, it will not restrict your development.

application

Let me give you some examples from my work to strengthen your confidence in learning. One is that when I write the OpenAPI, I do an intercept of the aspect and get the request parameters, as follows

The other one is that when I write single tests, public methods are easy to test, so I write objects directly. Method name, because I measure is private method, you directly point is not to point out, at this time how to do, is the reflection of the stage, the code is as followsThe final use is to use reflection to break singletons, as you can see from my previous post (The singleton pattern), and the prevention of destruction.

define

What is reflection? The mechanism of dynamically obtaining the contents of a class and dynamically calling the methods of an object and obtaining the properties is called the Reflection mechanism of JAVA.

  • For a given Class object, you can get all the properties and methods of that Class object.
  • For a given object (new XXXClassName
    ), can call any of its properties and methods.

Class object

First of all, let’s look at the next class object that contains a bunch of things that we can get at through reflection.There are four ways to get a class object:

Class<User> clazz1 = User.class; Class<? > clazz2 = Class.forName("com.jackxu.reflect.User");
        Class<? extends User> clazz3 = new User().getClass();
        // Class loaderClass<? > clazz4 = User.class.getClassLoader().loadClass("com.jackxu.reflect.User");
Copy the code

After obtaining the class object, we can obtain some structural information on the graph

        // Get the class modifier
        System.out.println(clazz1.getModifiers());
        System.out.println(clazz1.getPackage());
        System.out.println(clazz1.getName());
        System.out.println(clazz1.getSuperclass());
        System.out.println(clazz1.getClassLoader());
        System.out.println(clazz1.getSimpleName());
        // Get all interfaces with similar implementations
        System.out.println(clazz1.getInterfaces());
        System.out.println(clazz1.getAnnotations());
Copy the code

Field operations

Let’s start with two classes. One is the Person class, which has the following information

public class Person {

    public String idCard;

    private String userName;

    public void fun1(a) {}private void fun2(a) {}}Copy the code

Next comes the User class, which inherits from the Person class

public class User extends Person {

    private String name;

    public String sex;

    public static String address;

    public User(a) {}private User(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

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

    public String getName(a) {
        return name;
    }

    private void jump(a) {
        System.out.println("jump ... ");
    }

    public static void say(String msg) {
        System.out.println("say:"+ msg); }}Copy the code

So now we’re going to do our operation, again, we’re going to get a class object

        Class<User> clazz1 = User.class;
Copy the code

Let’s take a look at this class object and see that there are four methods on fields. Let’s look at them in turn

What’s the difference between getFields and getDeclaredFields

        // Retrieve the public fields of the current class and its parent class
        Field[] fields = clazz1.getFields();
        for (Field f : fields) {
            System.out.println(f.getModifiers() + "" + f.getName());
        }
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
        // Only get all fields in the current class
        Field[] declaredFields = clazz1.getDeclaredFields();
        for (Field f : declaredFields) {
            System.out.println(f.getModifiers() + "" + f.getName());
        }
Copy the code

To perform a

We combined with the above code category, to contrast the difference between actually I have written on the comments, the getFields method to obtain the current class, and all public fields in the parent class, while getDeclaredFields method to obtain only all fields in this class, including private. Know after these two methods the difference, we’ll look at another way getDeclaredField, this is for the current class of a particular field, the following is we get the name field, because the name field is private, so need to access permissions set to true, Finally, change the value of the name field of the User object to Jack Xu.

        Field nameFiled = clazz1.getDeclaredField("name");
        nameFiled.setAccessible(true);
        nameFiled.set(user, "jack xu");
        System.out.println(user.getName());
Copy the code

If the field is static and has no specific object, set the first argument to null in the set method.

        Field addressFiled = clazz1.getDeclaredField("address");
        addressFiled.set(null."shanghai");
        System.out.println(User.address);
Copy the code

Method of operation

The operation of a method is similar to that of a field, so let’s look at the methods below it as well

Let’s take a look at getMethods and getDeclaredMethods

        // Retrieve all public methods in the current class and its parent class
        Method[] methods = clazz1.getMethods();
        for (Method m : methods) {
            System.out.println(m.getModifiers() + "" + m.getName());
        }
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
        // Get all methods in this class, including private methods
        Method[] declaredMethods = clazz1.getDeclaredMethods();
        for (Method m : declaredMethods) {
            System.out.println(m.getModifiers() + "" + m.getName());
        }
Copy the code

GetMethods gets all the public methods in the current class and its parent class, and getDeclaredMethods gets all the methods in this class, including private methods.

GetDeclaredMethod (); getDeclaredMethod (); getDeclaredMethod (); getDeclaredMethod (); Non-static methods pass the corresponding instance object and parameters.

        Method jumpMethod = clazz1.getDeclaredMethod("jump");
        // Let go of private method calls
        jumpMethod.setAccessible(true);
        jumpMethod.invoke(user);
        // Static method calls
        Method sayMethod = clazz1.getDeclaredMethod("say", String.class);
        sayMethod.invoke(null."Hello.");
Copy the code

To perform a

Constructor operation

The constructor operates in the same way as above, with little difference

        // Get all public constructorsConstructor<? >[] constructors = clazz1.getConstructors();for (Constructor c : constructors) {
            System.out.println(c.getModifiers() + "" + c.getName());
        }
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
        // Get all constructorsConstructor<? >[] declaredConstructors = clazz1.getDeclaredConstructors();for (Constructor c : declaredConstructors) {
            System.out.println(c.getModifiers() + "" + c.getName());
        }
Copy the code

GetConstructors gets all public constructors. GetDeclaredConstructors gets all constructors in the class, including private constructors.

Of course, the application scenario of the constructor is to create objects, and here are a few ways to create objects by the way. The first is the most common way to do new, the second is through the newInstance method of the class object, the third is through the newInstance method of the constructor, the fourth is by implementing the Cloneable interface and calling the Clone method, and the fifth is by serializing and deserializing.

        //1
        User user1 = new User();
        //2, class object newInstance method
        User user2 = clazz1.newInstance();
        //3. The newInstance method of the constructor
        Constructor<User> declaredConstructor = clazz1.getDeclaredConstructor(String.class, String.class);
        declaredConstructor.setAccessible(true);
        User user3 = declaredConstructor.newInstance("jack xu"."Male");
        / / 4, clone
        / / 5 and Serializable
Copy the code

Pros and cons of reflection

Finally,, the pros and cons of reflection.

advantages

  • Increase the flexibility of the program, to avoid the inherent logic program written dead in the code
  • The code is concise and readable, which can improve the code reuse rate

disadvantages

  • Compared with direct invocation, the reflection performance decreases in the case of high volume
  • Internal exposure and safety hazards

Let’s do an experiment, create 10 million objects with new and 10 million objects with reflection, and see who takes the least time.

        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            User user = new User();
        }
        long end = System.currentTimeMillis();
        System.out.println("Total time to create with new:" + (end - start));

        Class<User> clazz = User.class;
        for (int i = 0; i < 10000000; i++) {
            clazz.newInstance();
        }
        long end2 = System.currentTimeMillis();
        System.out.println("Create total time using reflection:" + (end2 - end));
Copy the code

Run the

The result shows that the performance of reflection is about 8 times slower, so the low performance of reflection is not something to talk about, which is proved by data. What is the specific slow performance? It is mainly because the native method is called and the security check is done every newInstance, which is time-consuming.

conclusion

Reflection here is all over, this article introduces some commonly used methods and application scenarios, hope to bring help to everyone, reflection is the master play, but who would not want to become a master, in the way to become god, if you think it is good, please click like oh!