Domanda

Ho una classe di metodi statici che possono essere eseguiti su una mappa tenuta all'interno della classe e voglio che la mappa venga impostata quando viene chiamata la classe. Ho provato a usare un convolgente privato, ma non viene chiamato. Le parti pertinenti del mio codice sono:

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
}

Un costruttore privato è la cosa giusta da usare qui, e in tal caso cosa sto facendo di sbagliato?

Scusa se questo è un duplicato; Ho provato a cercare risposte, ma non sono sicuro di cosa cercare!

È stato utile?

Soluzione

Il blocco iniziale statico è stato menzionato in diverse altre risposte. Ma praticamente trovo il seguente linguaggio più frequentemente in natura:

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;
    }
}

Altri suggerimenti

No, un costruttore privato non è quello che vuoi. Un costruttore inizializza un esempio della tua classe (quando chiami new MyClass()), ma lo stato statico non appartiene a un'istanza e quindi non dovrebbe essere inizializzato dal costruttore. Inizializzazione che si desidera accadere quando la classe viene caricata per la prima volta dovrebbe essere in a static blocco posizionato a livello di classe.

static {
   populateMyMap();
}

Ma non dovresti mai usare lo stato statico (globale). Lo stato statico rende il tuo sistema proibitivamente difficile da testare, è più sfumato dello stato di istanza (ad esempio, hai una copia per carico della classe) ed è in genere più difficile rendere il thread sicuro.

Considera di rendere la tua mappa un Membro dell'istanza della tua classe invece.

Usa l'inizializzatore statico:

public class MyClass
{
    static {
    //init
    }
}

Esistono due modi per raggiungere questo obiettivo. Uno è quello di rendere il metodo "PopulatemyMap" un inizializzatore statico (o l'approccio suggerito da AH). Quindi è garantito per essere eseguito prima della prima chiamata statica. Questo di solito è il modo migliore, supponendo che il costo di eseguire PopulatemyMap sia abbastanza piccolo da non essere notato, o se si utilizza la funzionalità della classe quasi ogni volta che l'applicazione viene eseguita.

L'approccio alternativo è ciò che useresti se eseguire "populatemymap" è qualcosa che richiede un tempo significativo e o potresti non usare la funzionalità per alcune esecuzioni dell'app o si desidera differire l'esecuzione di PopulatemyMap fino ai dati è necessario, per non aumentare inutilmente il tempo di avvio.

Se il secondo approccio è quello che desideri, dovresti cambiare le strutture e utilizzare un singleton piuttosto che metodi statici. Rendi i metodi (e i dati) non statici e fai sì che ogni utente ottenga l'istanza Singleton prima di chiamare il metodo su di esso. Avere "populatemymap" chiamato nel costruttore (privato). Sì, lo so, i singleton hanno una cattiva reputazione e la gente dice sempre "evitali perché sono solo metodi globali sotto mentite spoglie", ma i metodi statici sono anche solo metodi globali. Non stai perdendo nulla. E in questo modo non si paga il costo dell'esecuzione di PopulatemyMap fino a quando (o a meno che) non sia necessario.

ATTENZIONE: se le tue strutture di dati non sono immutabili, cioè possono essere cambiate dopo che sono state inizializzate, probabilmente non dovresti usare nessuna di queste strutture.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top