Summary of java reflection mechanism development experience

I often use the reflection mechanism in practical projects, so I will take some summary notes on the learned reflection usage for future replay.

There is such a class:

package com.example.demo;
import com.alibaba.fastjson.annotation.JSONField;
public class User {
    private String name;
    @Value( value ="age_a")
    private String age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
     public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

1、 There are three ways to create a class

1 - Class clazz = Class. forName("com.example.demo.User");

Note that the class name of forname ("XXX") here needs to be a full name and an interface or class, otherwise it cannot be loaded.

2 - User user = new User();

Class clazz2 = user. getClass();

3 - Class clazz3 = User. class;

In the above three ways, you can get the class object of class user. Through class, you can start playing reflection.

2、 Reflection gets all properties and property types of the class

Class clazz = User.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
    System.out.println("属性名:"+field.getName());
    System.out.println("属性的类型:"+field.getGenericType().getTypeName());
}

Printout user properties and property types——

Attribute name: type of name attribute: Java Lang.string property name: type of age property: Java lang.String

After using reflection to obtain the field properties of the class, can reflection be used to create an object? The answer is yes.

For example, you can create an object by reflecting the field properties similar to the following code.

Map<String,Object> fileds = new HashMap<>();
fileds.put("name","张三");
fileds.put("age","10");
Object o = User.class.newInstance();
 Field[] fields = o.getClass().getDeclaredFields();
 for (Field field : fields) {
     //设置后可用反射访问访问私有变量
     field.setAccessible(true);
     //通过反射给属性赋值
     field.set(o,fileds.get(field.getName()));
 }
 User user1 = (User) o;
 System.out.println(user1.toString());

What scenarios might this be necessary? Like the mapping of some internal data and external data fields, the source data can be mapped to the target data through a similar field reflection method, and then the target object that can be inserted into the database can be obtained.

3、 Reflection dynamically modifies the annotation value of class properties

Note that when setting the user class, we annotated one of the fields: @ value (value = "age_a"). This is a set value annotation. Since it is a set value, can it be dynamically modified according to different situations during code operation?

The annotations on the field are actually stored in a membervalues attribute, which is a map, which can be obtained in this way——

Field[] fields = User.class.getDeclaredFields();
for (Field field : fields) {
    //设置后可用反射访问访问私有变量
    if ("age".equals(field.getName() )){
        field.setAccessible(true);
       //获取 annotation 这个代理实例所持有的 InvocationHandler
       InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(Value.class));
       // 获取 InvocationHandler 的 memberValues 字段
        Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
        memberValues.setAccessible(true);
        Map<String,Object> values = (Map<String,Object>) memberValues.get(invocationHandler);
        System.out.println(values);
    }
}

Debug break point, you can see——

This map < string, Object > stores all attribute values in the @ annotation. Here, @ value has only one value attribute——

public @interface Value {
    String value();
}

If you change it to something like @ jsonfield (name = "age_a"), slightly modify the code above, such as:

Field[] fields = User.class.getDeclaredFields();
for (Field field : fields) {
    if ("age".equals(field.getName() )){
        field.setAccessible(true);
          InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(JSONField.class));
		......
    }
}

@The internal properties of the jsonfield annotation are as follows——

Running the code just now, you can see that all the attributes and corresponding attribute values in this annotation are obtained and stored in map < string, Object >.

@H_ 301_ 97@

At this point, I return to the previous question. What should I do to dynamically change the value of this annotation?

In fact, it is very simple. You only need to set the value directly, for example——

InvocationHandler invocationHandler = Proxy.getInvocationHandler(field.getAnnotation(Value.class));
Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
memberValues.setAccessible(true);
Map<String,Object>) memberValues.get(invocationHandler);
values.put("value","new_age");
memberValues.setAccessible(false);

Just note that the key here needs to correspond to the attribute value in the annotation.

4、 Method and calling method of reflection acquisition class

 Object o=User.class.newInstance();
//通过反射获取到User的setAge方法,后面的String.class表示这个setAge方法的参数类型,若有多个,则按顺序列出
//同时,若为其他类型,如List,Long,则为List.class,Long.class
 Method m =  (Method) o.getClass().getmethod("setAge",String.class);
 m.invoke(o,"name");
 User user = (User) o;
 System.out.println(user);

It can be seen from the print that the age has been set to name, indicating that the setage call was successful.

Finally, an encapsulation tool for converting map into object is realized through reflection——

   public Object MapToObject(Object object,Map<String,Object> map) throws illegalaccessexception {
        Class cla =  object.getClass();
        Field[] fields = cla.getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            if("serialVersionUID".equals(field.getName()))continue;
            if(map.get(field.getName())!=null) {
                Object value=map.get(field.getName());
                value=convertValType(value,field.getType());
                field.set(object,value);
            }
        }
        return object;
    }


    private static Object convertValType(Object value,Class<?> fieldTypeClass) {
        Object o = null;
        if (Long.class.getName().equals(fieldTypeClass.getName())
                || long.class.getName().equals(fieldTypeClass.getName())) {
            o = Long.parseLong(value.toString());
        } else if (Integer.class.getName().equals(fieldTypeClass.getName())
                || int.class.getName().equals(fieldTypeClass.getName())) {
            o = Integer.parseInt(value.toString());
        } else if (Float.class.getName().equals(fieldTypeClass.getName())
                || float.class.getName().equals(fieldTypeClass.getName())) {
            o = Float.parseFloat(value.toString());
        } else if (Double.class.getName().equals(fieldTypeClass.getName())
                || double.class.getName().equals(fieldTypeClass.getName())) {
            o = Double.parseDouble(value.toString());
        } else {
            retVal = o;
        }
        return retVal;
    }

Welcome to the official account, about thinking, about culture, about growth.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>