Accéder à une variable private dans la classe d’une API avec Reflection
Eric Vialle | Mardi 10 novembre 2009 | 11:25
Certaines API, généralement dont les sources sont fermées ne permettent pas d’accéder à certaines valeurs d’un objet. En effet, dans la définition de leur classe, un champ a été mis à private et aucun getter n’a été mis à disposition. Ce problème m’est arrivé, alors que je développais un solution d’envoie de message par Bluetooth, un objet d’une API d’un développeur tierce contenait dans une variable privée contenant l’adresse MAC d’un utilisateur. Ne pouvant modifier le code source de mon collègue j’ai donc créé une classe respectant les propriété de cette classe tierce, mais permettant d’accéder en plus à ce champ privé.
Je vais ici vous décrire la solution que j’ai développé afin d’accéder à une variable private sans modifier le code source avec la méthode de la Reflection.
Considérons d’abord la classe PrivateDataClass contenant un champ privé dont on ne peut modifier le code source:
- /**
- * Classe contenant des données privées auxquelles
- * nous aimerions avoir accés.
- */
- public class PrivateDataClass {
- /**
- * Nous n'avons pas accés à myPrivateInt.
- * Mais nous aimerions!
- */
- private int myPrivateInt = 77;
- /**
- * Ceci est un exemple de méthode public
- */
- public void myMethod() {
- }
- }
Maintenant nous allons créer la classe héritant des propriétés de PrivateDataClass; PublicDataClass Nous implémenterons une méthode getMyPrivateInt() destinée à récupérer le champ myPrivateInt.

Schéma UML montrant PublicDataAccess permettant de récuperer une variable privée de PrivateDataAccess
- import java.lang.reflect.Field;
- /** Classe étandant une classe avec des champs privées. */
- public class PublicDataClass extends PrivateDataClass {
- /** On met ici la classe parente dont on hérite les données. */
- private final static Class PARENT_CLASS = PrivateDataClass.class;
- /**
- * Permet d'acceder au champs "myPrivateInt"
- * de PrivateDataClass.
- */
- public int getMyPrivateInt() {
- try {
- //1- on recupere la variable privée myPrivateInt de PrivateDataClass
- //2- On la rend accessible
- myPrivateField.setAccessible(true);
- //3- On recupere l'objet Int
- //4- L'autoboxing se chargera de le convertir en primitive int
- return myObject;
- e.printStackTrace();
- }
- //Valeur par défaut qui sera jamais atteinte
- return 0;
- }
- }
Cette classe peut ensuite être utilisée à la place d’une PrivateDataClass, comme on peut le voir dans ce test de PublicDataClass.
- /**
- * @author Eric VIALLE
- */
- public class Main {
- /**
- * @param args
- */
- PublicDataClass publicDataClass = new PublicDataClass();
- int value = publicDataClass.getMyPrivateInt();
- //Les autres méthodes de PrivateDataClass
- //sont toujours accessibles
- publicDataClass.myMethod();
- //PublicDataClass reste un PrivateDataClass
- //Si un objet de type PrivateDataClass est attendu,
- //On peut lui fournir PublicDataClass
- exemple(publicDataClass);
- }
- /**
- * @param monObjet est un PrivateDataClass
- */
- public static void exemple(PrivateDataClass monObjet) {
- "aussi un PrivateDataClass");
- }
- }
Ce Main nous affichera:
Private value: 77
This is a dummy method
PublicDataClass est aussi un PrivateDataClass





