Acabo de pasar media hora pensando en esto, he logrado arreglar mi código, pero no entiendo completamente lo que está sucediendo y me pregunto si alguien podría arrojar algo de luz sobre él.Inicialización de campo estático Java
tengo una clase tipo utils, que contiene unos campos estáticos (un punto extremo de conexión de base de datos, por ejemplo) que son utilizados por otros programas en función de la tarea en cuestión. Esencialmente una biblioteca.
Así es como se veía anteriormente (aunque todavía está roto);
//DBUtils.java
public final class DBUtils {
private static DBConnection myDBConnection = spawnDBConnection();
private static DBIndex myDBIndex = null;
private static DBConnection spawnDBConnection() {
//connect to the database
//assign a value to myDBIndex (by calling a method on the DBConnection object) <- IMPORTANT
//myDbIndex NOT NULL HERE
System.out.println("database connection completed");
//return the DBConnection object
}
public static searchDB(String name) {
//use the myDBIndex to find a row and return it
}
}
tan brevemente, estoy usando el método spawnDBConnection estática() para asignar un valor a tanto myDBConnection y myDBIndex. Esto funciona perfectamente, la primera línea de salida de mi programa siempre es "conexión de base de datos completada", ni myDBConnection ni myDBIndex son nulos al final del método spawnDBConnection(), todo es como debería ser.
Mi programa externo se ve así;
//DoSomethingUsefulWithTheDatabase.java
public final class DoSomethingUsefulWithTheDatabase {
public static void main(String args[]) {
DBUtils.searchDB("John Smith"); //fails with NullPointerException on myDBIndex!
}
}
Este llamado a searchDB sucede después de la spawnDBConnection ha terminado, he utilizado la salida estándar ampliamente para demostrar esto. Sin embargo, una vez dentro del método searchDB, ¡el valor de myDBIndex es nulo! Es un campo estático, y no fue nulo al final de spawnDBConnection, no se han realizado otras asignaciones, y ahora es nulo :(
La solución simple era eliminar el "= nulo", por lo que ahora se ve la declaración del campo similares;
private static DBIndex myDBIndex;
¿por qué que marcan la diferencia que estoy completamente confundido por éste
Considere hacer su estática 'final'. Te verás obligado a asignarlos exactamente una vez, eliminando este tipo de sorpresa. –
Esto es una terrible pesadilla-antipattern qué estás haciendo aquí. Está acoplando la inicialización de clase a la adquisición de una conexión de base de datos. –
No debe inicializar estáticamente DBConnection. ¿Qué pasa si myDBConnection se muere, vas a comenzar a usar DbUtils2 en tu código? –