Установить значение поля с отражением

Im работает с одним проектом, который не является open source, и мне нужно изменить один или несколько его классов.

в одном классе следующая коллекция:

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

все, что мне нужно сделать, это использовать отражение и использовать concurrenthashmap здесь. Я пробовал следующий код, но он не работает.

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

Ответы

Ответ 1

Надеюсь, это то, что вы пытаетесь сделать:

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(); 
    }
}

Он печатает:

value1

Ответ 2

Стоит прочитать Oracle Java Tutorial - Получение и установка значений полей

Поле # set (Объект объекта, значение объекта) устанавливает поле, представленное этим объектом Field в аргументе указанный объект, для указанное новое значение.

Это должно быть как

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

Вы не можете установить какое-либо значение в null Object Если попытаться, это приведет к NullPointerException


Примечание. Установка значения поля посредством отражения имеет определенный объем служебных накладных расходов, поскольку должны выполняться различные операции, такие как проверка разрешений доступа. С точки зрения времени выполнения эффекты одинаковы, и операция является такой же атомной, как если бы значение было изменено непосредственно в коде класса.

Ответ 3

Приведенный ниже метод устанавливает поле на вашем объекте, даже если поле находится в суперклассе

/**
 * 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

Вы можете попробовать следующее:

//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...");