web-dev-qa-db-fra.com

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 classes.

Dans une classe est la collection suivante:

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

Tout ce que je dois faire, c'est utiliser la réflexion et utiliser concurrenthashmap ici. J'ai essayé de suivre le code mais cela ne fonctionne pas.

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

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
34
Visruth

Cela vaut la peine de le lire Oracle Java Tutoriel - Obtention et définition des valeurs de champ

Field # set (Object object, Object value) définit le champ représenté par cet objet Field sur l'objet spécifié argument à la nouvelle valeur spécifiée.

Ça devrait être comme ça

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

Vous ne pouvez définir aucune valeur dans null Object Si vous essayez, vous obtiendrez alors NullPointerException


Remarque: La définition de la valeur d'un champ par réflexion a une certaine valeur de surcoût de performance car diverses opérations doivent être effectuées, telles que la validation. 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 avait été modifiée directement dans le code de classe.

17
Braj

La méthode ci-dessous définit un champ sur votre objet même s'il 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;
    }
}
7
Alex Burdusel

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