Pregunta

Tengo una clase de métodos estáticos que se pueden realizar en un mapa que se mantiene dentro de la clase, y quiero que el mapa se configure cuando se llama a la clase. He intentado usar un contratario privado, pero no se llama. Las partes relevantes de mi código son:

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
}

¿Es un constructor privado lo correcto para usar aquí, y si es así, qué estoy haciendo mal?

Lo siento si esto es un duplicado; He intentado buscar respuestas, ¡pero no estoy seguro de qué buscar!

¿Fue útil?

Solución

El bloque de inicializador estático se ha mencionado en varias otras respuestas. Pero prácticamente encuentro el siguiente idioma con más frecuencia en la naturaleza:

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

Otros consejos

No, un constructor privado no es lo que quieres. Un constructor inicializa un instancia de tu clase (cuando llamas new MyClass()), pero el estado estático no pertenece a una instancia y, por lo tanto, no debe inicializarse desde el constructor. La inicialización que desea que se realice cuando la clase se cargue por primera vez debe estar en un static Bloque colocado en el nivel de clase.

static {
   populateMyMap();
}

Pero nunca debe usar el estado estático (global). El estado estático hace que su sistema sea prohibitivamente difícil de probar, es más matizado que el estado de instancia (por ejemplo, tiene una copia por carga de la clase) y generalmente es más difícil hacer que el hilo sea seguro.

Considere hacer que su mapa sea un miembro de la instancia de tu clase en su lugar.

Use el inicializador estático:

public class MyClass
{
    static {
    //init
    }
}

Hay dos formas de lograr esto. Una es hacer del método "PopulatemyMap" un inicializador estático (o el enfoque sugerido por AH). Luego se garantiza que se ejecutará antes de la primera llamada estática. Esta suele ser la mejor manera, suponiendo que el costo de ejecutar PopulatEmymap es lo suficientemente pequeño como para no ser notado, o si va a utilizar la funcionalidad de la clase casi cada vez que se ejecuta la aplicación.

El enfoque alternativo es lo que usaría si ejecutar "PopulatEmymap" es algo que toma una cantidad significativa de tiempo y es posible que no use la funcionalidad para algunas ejecuciones de la aplicación, o si desea diferir la ejecución de PopulatEmimap hasta que los datos es necesario, para no aumentar innecesariamente el tiempo de inicio.

Si el segundo enfoque es lo que desea, entonces debe cambiar de estructura y usar un singleton en lugar de métodos estáticos. Haga que los métodos (y los datos) no estén static y haga que cada usuario de ellos obtenga la instancia de Singleton antes de llamar al método en él. Tener "PopulatEmymap" llamado en el constructor (privado). Sí, lo sé, los singletons tienen una mala reputación y la gente siempre dice "Evítalos porque son solo métodos globales disfrazados", pero los métodos estáticos también son solo métodos globales. No estás perdiendo nada. Y de esta manera no paga el costo de ejecutar PopulatEmyMap hasta (o a menos) que lo necesite.

Advertencia: si sus estructuras de datos no son inmutables, es decir, se pueden cambiar después de que se inicialicen, entonces probablemente no debería usar ninguna de estas estructuras.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top