Question

J'ai une classe de méthodes statiques qui peuvent être effectuées sur une carte tenue dans la classe, et je veux la carte à mettre en place lorsque la classe est appelée. Je l'ai essayé d'utiliser un contructor privé, mais ce n'est pas appelé. Les parties pertinentes de mon code sont les suivants:

public class MyClass
{
    private static final String KEYS = "ABC";
    private static final String[] DATA = {"AAA", "BBB", "CCC"};
    private static HashMap<Character, String> myMap;

    private MyClass() {
        System.out.println("Running constructor");
        populateMyMap();
    }

    private static void populateMyMap() {
        myMap = new HashMap<Character, String>();
        for (int i=0; i < KEYS.length; i++) {
            myMap.put(KEYS.charAt(i), DATA[i]);
        }
    }

    //various static methods
}

est un constructeur privé la bonne chose à l'aide ici, et si oui, qu'est-ce que je fais mal?

Désolé si cela est un double; J'ai essayé de chercher des réponses, mais je ne suis pas sûr de quoi chercher!

Était-ce utile?

La solution

Le statique initialiseur bloc a été mentionné dans plusieurs autres réponses. Mais en pratique, je trouve plus souvent l'idiome suivant dans la nature:

public class MyClass
{
    private static HashMap<Character, String> myMap = createMyMap();

    private static HashMap<Character, String> createMyMap() {
        HashMap<Character, String> myTmpMap = new HashMap<Character, String>();
        for (int i=0; i < KEYS.length; i++) {
            myTmpMap.put(KEYS.charAt(i), DATA[i]);
        }
        return myTmpMap;
    }
}

Autres conseils

Non, un constructeur privé n'est pas ce que vous voulez. Un constructeur initialise une par exemple de votre classe (lorsque vous appelez new MyClass()), mais l'état statique ne pas appartenir à une instance et ne devrait donc pas être initialisé à partir du constructeur. Initialisation que vous voulez arriver lorsque la classe est d'abord chargé doit être dans un bloc de static placé au niveau de la classe.

static {
   populateMyMap();
}

Mais vous ne devriez jamais être en utilisant l'état statique (global). état statique rend votre système excessivement difficile à tester, il est plus nuancée que l'état d'instance (par exemple, vous avez une copie par charge de la classe) et il est généralement plus difficile à faire thread-safe.

Pensez à faire votre carte un membre de l'instance de votre classe à la place.

Utilisez le statique initialiseur:

public class MyClass
{
    static {
    //init
    }
}

Il y a deux façons d'y parvenir. La première consiste à rendre la méthode « populateMyMap » un initialiseur statique (ou l'approche suggérée par l'Hégire). Ensuite, il est assuré d'être exécuté avant le premier appel statique. Ceci est généralement la meilleure façon, en supposant que soit le coût de fonctionnement populateMyMap est assez faible pour ne pas être remarqué, ou si vous allez utiliser la fonctionnalité de la classe presque à chaque fois que l'application est exécutée.

L'approche alternative est ce que vous utilisez si vous utilisez « populateMyMap » est quelque chose qui prend beaucoup de temps et soit vous soit peut-être pas utiliser la fonctionnalité pour certaines exécutions de l'application, ou si vous voulez reporter l'exécution de populateMyMap jusqu'à ce que les données sont nécessaires, pour ne pas le temps de démarrage augmenter inutilement.

Si la deuxième approche est ce que vous voulez, alors vous devriez changer de structures et d'utiliser un Singleton plutôt que des méthodes statiques. Faire les méthodes (et des données) non-statiques et ont chaque utilisateur de les obtenir l'instance Singleton avant d'appeler la méthode sur elle. Avoir « populateMyMap » appelé dans le constructeur (privé). Oui, je sais, singletons ont une mauvaise réputation et les gens disent toujours « les éviter parce qu'ils ne sont que des méthodes globales déguisées », mais les méthodes statiques sont également à des méthodes globales. Tu perds rien. Et cette façon, vous ne payez pas les frais d'exécution jusqu'à ce que populateMyMap (ou moins) que vous devez.

AVERTISSEMENT:. Si vos structures de données ne sont pas immuables, i.e. ils peuvent être modifiés après leur initialisées, alors vous ne devriez probablement pas utiliser l'une de ces structures

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top