2009-09-04 5 views
0

Je ne comprends absolument pas pourquoi le code suivant continue de lancer NullpointerExceptions. Je n'ai pas pu comprendre ou déboguer ceci (son code dépouillé d'une plus grande classe) ...L'ajout de "this" référence à Array échoue dans Java Constructeur

Le code est basé sur le "modèle Enum" et je veux garder une liste/carte de toutes les "constantes" qui sont contenus dans la classe (je pourrais être rÉFLEXION pour cela, mais en utilisant une liste/carte est beaucoup plus facile ...)

public class Country { 

     public static final Country SWITZERLAND = new Country("SWITZERLAND"); 

     private static ArrayList<Country> countries = new ArrayList<Country>(); 

     private Country(String constname) {  
      //constname is currently not used (I will use it for a Key in a Map) 
      System.out.println(constname); 
      System.out.println("Ref debug:"+this); 

      //Ad this to the Countries 
      Country.countries.add(this); 
     } 
    } 

aide serait très apprécié. Qu'est-ce que j'oublie ici?

+1

C'était un gerat d'apprentissage: pour résumer: L'ORDRE DES INITIALISATEURS STATIQUES EST PERTINENT !!! Merci beaucoup à tous ceux qui ont répondu !! – jan

+0

Les constructeurs auto-enregistrés ne sont vraiment pas une bonne idée. –

Répondre

4

développiez ce que Konrad a dit, les initialiseurs variables statiques sont exécutées dans l'ordre textuel (comme spécifié dans JLS section 8.7). Si vous mettez le premier ArrayList, il fonctionnera:

public class Country {  
    private static ArrayList<Country> countries = new ArrayList<Country>(); 

    public static final Country SWITZERLAND = new Country("SWITZERLAND"); 

... 

suggestion de Konrad d'utiliser un constructeur statique pour maintenir l'ordre clairement spécifié est un bon cependant.

Utilisez-vous Java "pre 1.5"? Sinon, utilisez une énumération ...

+0

+1 ... Je ne parle pas couramment Java, donc je n'étais pas sûr de l'ordre d'initialisation. Puisque Jon dit que c'est textuel, cette solution est supérieure au bloc 'static' (IMHO). –

5

SWITZERLAND, étant statique, est potentiellement initialisés avantcountries, qui est aussi static. Par conséquent, countries est toujours null dans l'appel de constructeur de SWITZERLAND.

Pour forcer un ordre bien défini d'initialisation, utilisez un bloc static:

public class Country { 

    public static final Country SWITZERLAND; 

    private static ArrayList<Country> countries; 

    static { 
     countries = new ArrayList<Country>(); 
     SWITZERLAND = new Country("SWITZERLAND"); 
    } 
} 
+0

L'ordre d'initialisation est toujours bien défini. Il est effectué dans l'ordre du texte. +1 pour le bloc d'initialisation statique. L'ordre d'exécution est plus clair pour le lecteur de cette façon. –

1

L'appel du constructeur «Pays» pour initialiser SWITZERLAND se produit avant l'initialisation de la liste countries. Si vous changez l'ordre de la définition du champ statique, cela fonctionnera mieux.

-1

Je pense que le code ci-dessous peut fonctionner. Constructeur de classe doit définir comme méthode publique pas privé.

Pays (String constname) {//
constname actuellement pas utilisé (je vais l'utiliser pour une clé dans une carte) System.out.println (constname); System.out.println ("Ref debug:" + this);

 //Ad this to the Countries 
     Country.countries.add(this); 
    } 
+0

La visibilité du constructeur n'a rien à voir avec le problème. – mikej

4

Parce que je pense que cela mérite plus que la mention sommaire Jon lui a donné:

Le "modèle typesafe enum" est obsolète!

Sauf si vous êtes obligé d'utiliser une ancienne version Java (avant la version 1.5, qui ne sont même pas pris en charge plus par Sun), vous devez utiliser Java de real Enums que vous enregistrez beaucoup de travail et les tracas (parce que le vieux style les enums typesafe sont très difficiles à obtenir) et sont tout simplement géniaux.

Questions connexes