Day_ 8/23 (Talking about Reflection Concept)

Catalog

Preface

1. Introduction of Reflection

2. Steps for using reflection

1. Get byte code object

1.1 What is a byte code object

3 ways to get byte code objects

2. Get construction methods, member methods, properties from byte code files

2.1 Get the construction method (Constructor class type)

2.2 Get Member Method (Method Class Type)

2.3 Get Properties (Field Class Type)

3. Use construction methods, member methods, attributes

3.1 Use construction methods

3.2 Use member method

3.3 Use member variables

summary

Preface

You don't know if you've ever thought about this. When we write code using IDEA integrated development tools, idea can tell you what methods and attributes are contained in the classes you are currently using, whether they're our own or not, and how does it do that? The answer is to use the reflection mechanism. Learn about reflection today.

1. Introduction of Reflection

Reflection is one of the features of the Java programming language that allows running Java programs to examine themselves. Private encapsulated resources can only be accessed internally by classes, not externally, but reflection can directly manipulate class private properties. Reflection captures all information about a class at run time (including member variables, member methods, constructors, and so on), and manipulates fields, methods, constructors, and so on.

2. Steps for using reflection

1. Get byte code object

1.1 What is a byte code object

Byte code objects are Class class objects (where Class is a class, not the class keyword when we define classes, which is interesting) for each class. The class file is a byte code object. The.Class file, as we know, is a compiled file of code we write that contains all the information about the class in the source code. In this case, all the information about the class can be obtained from the byte code object.

3 ways to get byte code objects

Class name. Class, this is a simple way to do it, but be aware that it requires a package, that is, if you want the virtual machine to find your class, it will make a mistake if it cannot find it

Object name. getClass(), which is also a way of doing this, but I have a question, since there are objects, its method can be called directly.

Class.forName("package name plus class name"), which should be the best way to execute the code anywhere, is fine under different packages.

Note here that there is only one byte code file for each Class, so the lass object obtained in three ways is the same. See the code demonstration:

public class MainTest {
    public static void main(String[] args) throws ClassNotFoundException {
//        Get byte code object
        //Class name. class get, MainTest class and TestClass class under the same package
        Class<TestClass> aClass = TestClass.class;
        //Object name. getClass() get, need to create a new object first
        TestClass testClass = new TestClass();
        Class<? extends TestClass> aClass1 = testClass.getClass();
        //Class.forName("Package name + Class name") Get
        Class<?> aClass2 = Class.forName("com.fs.test823.TestClass");

        //==The address of the object when compared, if different references point to the object at the same address,
        //Then they refer to the same object
        System.out.println("aClass and aClass1 Is the same object:"+(aClass == aClass1));
        System.out.println("aClass and aClass2 Is the same object:"+(aClass == aClass2));
        System.out.println("aClass1 and aClass2 Is the same object:"+(aClass1 == aClass2));

    }
}

Run result:

2. Get construction methods, member methods, properties from byte code files

2.1 Get the construction method (Constructor class type)

Public Constructor <T> getConstructor (Class <?>... parameterTypes) This method requires a byte code object of type parameter to be passed in, either none, one or more, and returns a Constructor object depending on the number of parameters in the constructor.

Public Constructor <?> [] getConstructors() This method does not require parameters and returns an array of Constructor type.

The public Constructor <T> getDeclaredConstructor (Class <?>... parameterTypes) method requires the same parameters and return values as the first method.

Public Constructor <?> [] getDeclaredConstructors () This method has the same return value as the second method. The first two methods can only obtain public-modified constructs, while the third four methods can obtain all constructs.

2.2 Get Member Method (Method Class Type)

Similar to the get construction method, there are four ways to get members

Public Method getMethod (String name, Class<?>... parameterTypes) This method is similar to the getConstructor method in that it returns a Method object, except that the first parameter of the method is the method name (String type) of the member method you need to obtain.

public Method[] getMethods() is similar to the getConstructors method and returns an array of type Method.

        public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

public Method[] getDeclaredMethods() is the same, the first two methods get public-modified member methods, and the last two methods get all member methods.

2.3 Get Properties (Field Class Type)

The same is true for getting attributes, with four methods:

         public Field[] getField(String name)

         public Field[] getFields()

         public Field[] getDeclaredField(String name)

public Field[] getDeclaredFields() is similar to the previous one, but you only need to pass in the property name to get a single property.

3. Use construction methods, member methods, attributes

Create a new TestClass class. Write test code in the MainTest class to get the contents of the TestClass class. The contents of the TestClass are as follows:

public class TestClass {
    public String str;
    private int i;
    public TestClass() {
    }

    public TestClass(String str, int i) {
        this.str = str;
        this.i = i;
    }

    private TestClass(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "str="+str+"\ti="+i;
    }

    public void test(){
        System.out.println("I am public Modification test()Method");
    }

    private void test1(){
        System.out.println("I am private Modification test1()Method");
    }
    
    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }
}

3.1 Use construction methods

The newInstance method is required for the use of construction methods, see the code demonstration

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class MainTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//        Get byte code object
        //Class name. class get, MainTest class and TestClass class under the same package
        Class<TestClass> aClass = TestClass.class;

        //Get parameterless construction method
        Constructor<TestClass> constructor1 = aClass.getConstructor();
        //Get full parameters construction method
        Constructor<TestClass> constructor2 = aClass.getConstructor(String.class,int.class);
        //Getting the construction method of the private modification
        Constructor<TestClass> constructor3 = aClass.getDeclaredConstructor(String.class);

        //Construct with full parameters
        TestClass testClass = constructor2.newInstance("dog", 123); //Equivalent to TestClass testClass = new TestClass("dog", 123);
        //Override toString method
        System.out.println(testClass);

        //Use private uniparameter construction
        //Set Violent Reflex first when using private methods or properties, otherwise IllegalAccessException exception will be reported
        constructor3.setAccessible(true);
        TestClass testClass1 = constructor3.newInstance("fish");
        System.out.println(testClass1);
    }
}

Run result:

Successfully acquire the construction method, create the object, and assign values to the attributes. Notable here is the violent reflection, if there is no constructor3.setAccessible(true); This code throws an IllegalAccessException exception, as well as when using private member methods and attributes.

3.2 Use member method

The invoke method is required for the use of member methods, see the code demonstration

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MainTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//        Get byte code object
        //Class name. class get, MainTest class and TestClass class under the same package
        Class<TestClass> aClass = TestClass.class;

        //Get Public Method
        Method test = aClass.getMethod("test");
        //Get Private Method
        Method test1 = aClass.getDeclaredMethod("test1");

        //Use public methods
        //Unlike using a construction method here, invoke's first argument is the object of the class in which the method is executed
        //Use aClass.newInstance() can create an object of the class represented by aClass, but this method relies on parameterless construction and will report an InstantiationException exception if the class has no parameterless construction
        test.invoke(aClass.newInstance());
        //Use private methods
        //Similarly, a violent response is required before using a private method
        test1.setAccessible(true);
        test1.invoke(aClass.newInstance());
    }
}

Run Results

Both methods ran successfully.

3.3 Use member variables

Attributes are used slightly differently, depending on the data type, and the methods to get the values of the attributes are:

         Object get(Object obj)

         int getInt(Object obj)

         long getLong(Object obj)

         boolean getBoolean(Object ob)

         double getDouble(Object obj)

There are several ways to set the value of an attribute:

         void set(Object obj, Object value)

         void setInt(Object obj, int i)

         void setLong(Object obj, long l)

         void setBoolean(Object obj, boolean z)

         void setDouble(Object obj, double d)

This TestClass contains a String type data and an int type data, so just use the get and getInt methods to get the value of the property, set the same value, and see the code demonstration:

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class MainTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//        Get byte code object
        //Class name. class get, MainTest class and TestClass class under the same package
        Class<TestClass> aClass = TestClass.class;

        //Create a testClass object, which is needed later because the properties str and i are non-static and depend on the object to exist
        TestClass tc = new TestClass();
        //Get Public Properties
        Field str = aClass.getField("str");
        //Get Private Properties
        Field i = aClass.getDeclaredField("i");
        //Use public attributes
        System.out.println("to str Before assignment str The value of:"+str.get(tc));
        str.set(tc,"cat");
        System.out.println("to str After assignment str The value of:"+str.get(tc));
        //Use private properties
        //Set Violent Reflex
        i.setAccessible(true);
        System.out.println("to i Before assignment i The value of:"+i.getInt(tc));
        i.set(tc,147);
        System.out.println("to i After assignment i The value of:"+i.getInt(tc));

    }
}

Run result:

summary

This article briefly introduces reflection and uses it simply. It should be reflected in a framework, which should be combined with the set of attributes and configuration files described in yesterday's article. This will greatly increase the flexibility of the program and make it easier for users to access the framework without touching it.

This concludes the article. Thank you for your reading and wish you a happy life!

Tags: Java

Posted by ozzysworld on Fri, 26 Aug 2022 21:39:14 +0300