web-dev-qa-db-fra.com

Définir la valeur du champ privé avec réflexion

J'ai 2 classes: Father et Child

public class Father implements Serializable, JSONInterface {

    private String a_field;

    //setter and getter here

}

public class Child extends Father {
    //empty class
}

Avec réflexion, je souhaite définir a_field dans la classe Child:

Class<?> clazz = Class.forName("Child");
Object cc = clazz.newInstance();

Field f1 = cc.getClass().getField("a_field");
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc.getClass());
System.out.println("field: " + str1);

mais j'ai une exception:

Exception dans le fil "principal" Java.lang.NoSuchFieldException: a_field

Mais si j'essaye:

Child child = new Child();
child.setA_field("123");

Ça marche.

En utilisant la méthode setter j'ai le même problème:

method = cc.getClass().getMethod("setA_field");
method.invoke(cc, new Object[] { "aaaaaaaaaaaaaa" });
25
user1066183

Pour accéder à un champ privé, vous devez définir Field::setAccessible sur true. Vous pouvez retirer le champ de la super classe. Ce code fonctionne:

Class<?> clazz = Child.class;
Object cc = clazz.newInstance();

Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
80
John McClean

Utilisation d'Apache commons-lang3:

FieldUtils.writeField(childInstance, "a_field", "Hello", true);

Le "vrai" l'oblige à se mettre, même avec "privé".

21
David Lavender

Celui-ci peut aussi accéder à des champs privés sans rien faire

import org.Apache.commons.lang3.reflect.FieldUtils;
Object value = FieldUtils.readField(entity, fieldName, true);
4
Sacky San

Vous pouvez utiliser Manifold@Jailbreak pour une réflexion Java directe et sécurisée au type:

@Jailbreak Child child = new Child();
child.a_field = "123;

@Jailbreak déverrouille la variable locale enfant dans le compilateur pour un accès direct à tous les membres de la hiérarchie Child.

De même, vous pouvez utiliser la méthode d'extension jailbreak () pour une utilisation unique:

child.jailbreak().a_field = "123";

Avec la méthode jailbreak(), vous pouvez accéder à n’importe quel membre de la hiérarchie de Child.

Dans les deux cas, le compilateur résout l'accès au champ pour vous en toute sécurité, comme s'il s'agissait d'un champ public, tandis que Manifold génère pour vous un code de réflexion efficace.

En savoir plus sur Collecteur .

0
Scott McKinney