2009-08-10 9 views
3

Je n'ai eu d'autre choix que d'accéder à un ensemble de classes, que je ne peux pas modifier, avec cette structure par réflexion. Toutefois, l'utilisation de la méthode indiquée dans la méthode principale ci-dessous renvoie une exception NullPointerException. Le pointeur null étant "table" dans le constructeur lorsque f1.get (null) est appelé.Accéder de manière réfléchie à une variable statique dans une classe Java

Je ne peux pas instancier les classes au préalable car le seul constructeur est celui qui est privé. Donc, il n'y a aucun moyen pour moi de définir explicitement la table non plus.

Quelqu'un sait-il un moyen pour moi d'appeler de manière réfléchie Legacy.A?

public class Legacy { 
    public static final Legacy A = new Legacy("A"); 
    public static final Legacy B = new Legacy("B"); 

    private String type0; 
    private static Map<String, Legacy> table = new HashMap<String, Legacy>(); 

    private Legacy(String id) { 
     type0 = id; 
     table.put(type0, this); 
    } 

    public static void main(String[] args) throws Exception { 
     Field f1 = Legacy.class.getDeclaredField("A"); 
     Object o = f1.get(null);  
    } 
} 

Avant "Réflexion == BAD !!!"

+0

En fait, je ne vois pas comment vous pouvez accéder à Legacy.A sans NPE, réflexion ou non (remplacez ce code de réflexion par 'Object o = Legacy.A' pour que cela se produise). Lorsque j'ai essayé d'exécuter votre code, l'exception s'est produite lors de l'initialisation de la classe. – kdgregory

+0

C'est ce que je reçois pour avoir du code auto-formaté sur les sauvegardes. – Andrew

Répondre

7

L'ordre des initialiseurs statiques est faux, la table doit précéder les appels du constructeur.

C'est la raison pour laquelle vous obtenez l'exception lorsque la classe est chargée et initialisée. Cela n'a rien à voir avec la réflexion.

0

J'ai essayé, parce que je ne pouvais pas voir ce qui n'allait pas avec votre exemple. Il a travaillé si je réorganisés les déclarations:

import java.lang.reflect.Field; 
import java.util.HashMap; 
import java.util.Map; 

public class Legacy { 
    private String type0; 
    private static Map< String, Legacy > table = new HashMap< String, Legacy >(); 

    private Legacy(String id) { 
     type0 = id; 
     table.put(type0, this); 
    } 
    public static final Legacy A = new Legacy("A"); 
    public static final Legacy B = new Legacy("B"); 

    public static void main(String[] args) throws Exception { 
     Field f1 = Legacy.class.getDeclaredField("A"); 
     Object o = f1.get(null); 
    } 
} 

Les déclarations statiques ont besoin le constructeur (précédent).

4

Depuis cela est source de confusion, je l'écrire comme ceci:

public class Legacy { 
     static { 
      table = new HashMap<String, Legacy>(); 
      A = new Legacy("A"); 
      B = new Legacy("B"); 
     } 

     public static final Legacy A; 
     public static final Legacy B; 

     private String type0; 
     private static Map<String, Legacy> table; 

     private Legacy(String id) { 
       type0 = id; 
       table.put(type0, this); 
     } 

    public static void main(String[] args) throws Exception { 
       Field f1 = Legacy.class.getDeclaredField("A"); 
       Object o = f1.get(null);   
     } 
} 

De cette façon, même si les membres changent l'emplacement (en raison de refactoring, l'alignement de la ligne ou autre) le code sera toujours travailler.

Questions connexes