Java, establecer el valor del campo con la reflexión
reflection field (4)
El método a continuación establece un campo en su objeto incluso si el campo está en una superclase
/**
* 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;
}
}
Estoy trabajando con un proyecto que no es opensource y necesito modificar una o más de sus clases.
en una clase es siguiente colección:
private Map<Integer, TTP> ttp = new HashMap<>();
todo lo que necesito hacer es usar la reflexión y usar el mapa de mapa concurrente aquí. He intentado seguir el código pero no funciona.
Field f = ..getClass().getDeclaredField("ttp");
f.setAccessible(true);
f.set(null, new ConcurrentHashMap<>());
Espero que esto sea algo que estás tratando de hacer:
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();
}
}
Se imprime:
value1
Puedes probar esto:
//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...");
Vale la pena leer Oracle Java Tutorial - Obtención y configuración de valores de campo
Field # set (Objeto objeto, valor Objeto) establece el campo representado por este objeto Field
en el argumento del objeto especificado en el nuevo valor especificado.
Deberia ser asi
f.set(objectOfTheClass, new ConcurrentHashMap<>());
No puede establecer ningún valor en el objeto null
Si se intenta, se generará una NullPointerException
Nota: establecer el valor de un campo a través de la reflexión tiene una cierta cantidad de sobrecarga de rendimiento porque se deben realizar varias operaciones, como validar permisos de acceso. Desde el punto de vista del tiempo de ejecución, los efectos son los mismos y la operación es tan atómica como si el valor se cambiara en el código de clase directamente.