Set field value with reflection

2020-01-29 07:16发布

问题:

I'm working with one project which is not opensource and I need to modify one or more its classes.

In one class is following collection:

private Map<Integer, TTP> ttp = new HashMap<>(); 

All what I need to do is use reflection and use concurrenthashmap here. I've tried following code but it doesnt work.

Field f = ..getClass().getDeclaredField("ttp");
f.setAccessible(true);
f.set(null, new ConcurrentHashMap<>());

回答1:

Hope this is something what you are trying to do :

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Test {

    private Map ttp = new HashMap(); 

    public  void test() {
        Field declaredField =  null;
        try {

            declaredField = Test.class.getDeclaredField("ttp");
            boolean accessible = declaredField.isAccessible();

            declaredField.setAccessible(true);

            ConcurrentHashMap<Object, Object> concHashMap = new ConcurrentHashMap<Object, Object>();
            concHashMap.put("key1", "value1");
            declaredField.set(this, concHashMap);
            Object value = ttp.get("key1");

            System.out.println(value);

            declaredField.setAccessible(accessible);

        } catch (NoSuchFieldException 
                | SecurityException
                | IllegalArgumentException 
                | IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    public static void main(String... args) {
        Test test = new Test();
        test.test(); 
    }
}

It prints :

value1


回答2:

It's worth reading Oracle Java Tutorial - Getting and Setting Field Values

Field#set(Object object, Object value) sets the field represented by this Field object on the specified object argument to the specified new value.

It should be like this

f.set(objectOfTheClass, new ConcurrentHashMap<>());

You can't set any value in null Object If tried then it will result in NullPointerException


Note: Setting a field's value via reflection has a certain amount of performance overhead because various operations must occur such as validating access permissions. From the runtime's point of view, the effects are the same, and the operation is as atomic as if the value was changed in the class code directly.



回答3:

The method below sets a field on your object even if the field is in a superclass

/**
 * Sets a field value on a given object
 *
 * @param targetObject the object to set the field value on
 * @param fieldName    exact name of the field
 * @param fieldValue   value to set on the field
 * @return true if the value was successfully set, false otherwise
 */
public static boolean setField(Object targetObject, String fieldName, Object fieldValue) {
    Field field;
    try {
        field = targetObject.getClass().getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        field = null;
    }
    Class superClass = targetObject.getClass().getSuperclass();
    while (field == null && superClass != null) {
        try {
            field = superClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            superClass = superClass.getSuperclass();
        }
    }
    if (field == null) {
        return false;
    }
    field.setAccessible(true);
    try {
        field.set(targetObject, fieldValue);
        return true;
    } catch (IllegalAccessException e) {
        return false;
    }
}


回答4:

You can try this:

//Your class instance
Publication publication = new Publication();

//Get class with full path(with package name)
Class<?> c = Class.forName("com.example.publication.models.Publication");

//Get method
Method  method = c.getDeclaredMethod ("setTitle", String.class);

//set value
method.invoke (publication,  "Value to want to set here...");


回答5:

You can try this:

static class Student {
    private int age;
    private int number;

    public Student(int age, int number) {
        this.age = age;
        this.number = number;
    }

    public Student() {
    }
}
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
    Student student1=new Student();
   // Class g=student1.getClass();
    Field[]fields=student1.getClass().getDeclaredFields();
    Field age=student1.getClass().getDeclaredField("age");
    age.setAccessible(true);
    age.setInt(student1,13);
    Field number=student1.getClass().getDeclaredField("number");
    number.setAccessible(true);
    number.setInt(student1,936);

    for (Field f:fields
         ) {
        f.setAccessible(true);

        System.out.println(f.getName()+" "+f.getInt(student1));

    }
}

}