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<>());
22
demandé sur user2749903 2014-06-07 11:25:43

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
20
répondu Visruth 2015-05-02 05:30:49

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.

13
répondu Braj 2014-06-07 07:53:09

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;
    }
}
5
répondu Alex Burdusel 2017-03-28 20:31:26

, 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
répondu VK321 2017-11-25 12:31:40