Java, définir la valeur du champ avec réflexion
Je travaille avec un projet qui n'est pas opensource et j'ai besoin de modifier une ou plusieurs de ses classes.
Dans une classe est la collection suivante:
private Map<Integer, TTP> ttp = new HashMap<>();
Tout ce que je dois faire est d'utiliser la réflexion et d'utiliser concurrenthashmap ici. j'ai essayé de suivre le code mais ça ne marche pas.
Field f = ..getClass().getDeclaredField("ttp");
f.setAccessible(true);
f.set(null, new ConcurrentHashMap<>());
4 réponses
J'espère que c'est quelque chose que vous essayez de faire:
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();
}
}
Il imprime :
value1
Il vaut la peine de lire Oracle Java Tutorial-obtenir et définir les valeurs de champ
Champ#set(Object object, object value) définit le champ représenté par ce Field
objet sur la objet spécifié argument spécifié nouvelle valeur.
Ça devrait être comme ça
f.set(objectOfTheClass, new ConcurrentHashMap<>());
Vous ne pouvez définir aucune valeur dans l'objet null
si essayé, il en résultera NullPointerException
Remarque: définir la valeur d'un champ via la réflexion a une certaine quantité de surcharge de performance {[23] } Car diverses opérations doivent se produire telles que la validation des autorisations d'accès. Du point de vue de l'exécution, les effets sont les mêmes et l'opération est aussi atomique que si la valeur a été modifiée directement dans le code de classe.
La méthode ci-dessous définit un champ sur votre objet même si le champ est dans une superclasse
/**
* 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;
}
}
, Vous pouvez essayer ceci:
//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...");