El orden de inicialización de clases en Java (class initialization order) determina en qué secuencia se inicializan los campos, bloques y constructores. En resumen:
class Parent { static { System.out.println("Parent static"); } { System.out.println("Parent init"); } Parent() { System.out.println("Parent constructor"); } } class Child extends Parent { static { System.out.println("Child static"); } { System.out.println("Child init"); } Child() { System.out.println("Child constructor"); } } // new Child() -> ¿qué orden?
La salida será:
Primero los bloques estáticos de los padres, luego los bloques estáticos de los hijos, y luego los bloques no estáticos y los constructores en orden de herencia.
Pregunta: ¿Cuándo se ejecutarán los inicializadores estáticos en la clase:
class Ex {
static { System.out.println("static"); }
}
— al crear la primera instancia o al primer uso de cualquier método/campo estático?
Respuesta: El inicializador estático se ejecuta al primer acceso a la clase, incluyendo el acceso a cualquier miembro estático (método/campo), y no solo al crear una instancia.
Historia
En una aplicación bancaria, el grupo de conexiones estáticas se inicializaba en un bloque estático, pero debido al acceso a un método estático antes de crear la primera instancia, la conexión aún no se había creado. Esto llevó a un NullPointerException al ejecutarse bajo carga.
Historia
El servicio de registro dependía de un campo no estático, que se inicializaba después de la llamada al constructor de la clase base. Los registros se escribían en un registrador nulo, y se perdieron importantes mensajes de error.
Historia
Al agregar un nuevo campo con un valor inicial, el desarrollador lo colocó después del bloque de inicialización: el bloque intentaba usar un campo no inicializado, lo que llevaba a errores durante el arranque de la aplicación y complicadas búsquedas de la causa.