Frage

Ich habe eine Klasse statischer Methoden, die auf einer Karte in der Klasse durchgeführt werden können, und ich möchte, dass die Karte eingerichtet wird, wenn die Klasse aufgerufen wird. Ich habe versucht, einen privaten Conctortor zu verwenden, aber er wird nicht angerufen. Die relevanten Teile meines Codes sind:

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
}

Ist ein privater Konstruktor hier das Richtige, und wenn ja, was mache ich falsch?

Entschuldigung, wenn dies ein Duplikat ist; Ich habe versucht, nach Antworten zu suchen, aber ich bin mir nicht sicher, wonach ich suchen soll!

War es hilfreich?

Lösung

Der statische Initialisiererblock wurde in mehreren anderen Antworten erwähnt. Aber praktisch finde ich die folgende Idiom häufiger in freier Wildbahn:

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

Andere Tipps

Nein, ein privater Konstruktor ist nicht das, was Sie wollen. Ein Konstruktor initialisiert eine Beispiel Ihrer Klasse (wenn Sie anrufen new MyClass()), aber statischer Zustand gehört nicht zu einer Instanz und sollte daher nicht vom Konstruktor initialisiert werden. Initialisierung, die Sie beim ersten geladenen Unterricht aufnehmen möchten, sollte in a sein static Block auf der Klassenebene platziert.

static {
   populateMyMap();
}

Aber Sie sollten niemals den statischen (globalen) Zustand verwenden. Der statische Zustand macht Ihr System unerschwinglich schwierig zu testen, es ist nuancierter als der Instanzzustand (zum Beispiel haben Sie eine Kopie pro Last der Klasse) und es ist in der Regel schwieriger, den Thread sicher zu machen.

Erwägen Sie, Ihre Karte zu einer Karte zu machen Instanzmitglied stattdessen Ihrer Klasse.

Verwenden Sie den statischen Initialisierer:

public class MyClass
{
    static {
    //init
    }
}

Es gibt zwei Möglichkeiten, dies zu erreichen. Eine soll die "populatemymap" -Methode zu einem statischen Initialisierer (oder dem von AH vorgeschlagenen Ansatz) machen. Dann wird garantiert vor dem ersten statischen Anruf ausgeführt. Dies ist normalerweise der beste Weg, vorausgesetzt, entweder die Kosten für das Ausführen von Populatemymap sind klein genug, um nicht bemerkt zu werden, oder wenn Sie die Funktionalität der Klasse fast jedes Mal verwenden, wenn die Anwendung ausgeführt wird.

Der alternative Ansatz ist das, was Sie verwenden würden, wenn "Populatemymap" ausgeführt wird, das viel Zeit in Anspruch nimmt, und entweder verwenden Sie entweder die Funktionalität für einige Ausführungen der App oder Sie möchten die Ausführung von Populatemymap bis zur Daten verschieben ist erforderlich, um die Startzeit nicht unnötig zu erhöhen.

Wenn der zweite Ansatz das ist, was Sie wollen, sollten Sie Strukturen wechseln und eher ein Singleton als statische Methoden verwenden. Machen Sie die Methoden (und Daten) nicht statisch und lassen Sie jeden Benutzer die Singleton-Instanz erhalten, bevor Sie die Methode darauf aufrufen. "Populatemymap" im (privaten) Konstruktor aufgerufen werden. Ja, ich weiß, Singletons haben einen schlechten Ruf und die Leute sagen immer: "Vermeiden Sie sie, weil sie nur globale Methoden in Verkleidung sind", aber statische Methoden sind auch nur globale Methoden. Du verlierst nichts. Und auf diese Weise zahlen Sie nicht die Kosten für die Ausführung von Populatemymap, bis Sie (oder sofern) Sie müssen.

WARNUNG: Wenn Ihre Datenstrukturen nicht unveränderlich sind, dh sie können nach ihrer Initialisierung geändert werden, dann sollten Sie wahrscheinlich keine dieser Strukturen verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top