Установить значение поля с отражением
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...");