Bloques estáticos

Hace poco tuve una conversación con un amigo acerca del uso de bloques estáticos y pues sabíamos muy poco de ellos, dicha platica nos hizó investigar más sobre el tema, lo cual originó que escribierá sobre usos, ventajas y desventajas de los bloques estáticos:

Primero toca definir que es un bloque estático: también conocido como inicializador estático es aquel bloque de código que pertenece a una clase o interface y se define entre llaves de código precedidas por la palabra reservada static como se presenta el siguiente fragmento de código:

    public class Ejemplo{

         static int numero;        

         static{
             System.out.println("Esto se imprime dentro de un bloque estático o inicializador estático");
             numero = 10;
         }
         
        public static void main(String [] args){
             
        }
    }

Su tarea principal es la de inicializar las variables estáticas, por ello son conocidos como inicializadores estáticos, en el ejemplo se inicializa la variable "numero", pero se preguntaran cual sería la diferencia de inicializarla en un metodo estático o directamente cuando se declara,

En comparación con la inicialización dentro de un metódo estático podemos mencionar que el bloque estático solo se ejecuta una sola vez cada que la clase a la que pertenece es cargada por un classloader, y el metódo estatico se puede ejecutar cuantas veces se desee, es decir el número de veces que se invoque:

Por lo tanto el uso de bloques estáticos se adecua más para la inicialización de constantes pues solo se ejecuta una sola ocasión (yo antes lo entendia como una especie de constructor para la parte estática del PermGen, aunque no es lo mismo, ni creo que sea correcto llamarlo así), lo cual no impide que tambien se usen bloques estáticos para dar un valor inicial a una variable que pueda cambiar durante la ejecución del programa.

Bloque estático vs Metodo estático

    public class Ejemplo2{

         static int numero;

        static
        {
                System.out.println("Esto solo se imprime cuando la clase es cargada por un classloader");
                numero = 10;  // <-- Se inicializa una sola vez.
        }

        public static void inicializar(int numero) {
                Ejemplo2.numero = numero; // <-- El metodo inicializar puede cambiar su valor cuantas veces se invoque.
                System.out.println("Valor cambio al invocar inicializar: " + Ejemplo2.numero);
        }

        public static void main(String[] args) {
                System.out.println("Valor inicial: " + Ejemplo2.numero);
                Ejemplo2.inicializar(5);
                Ejemplo2.inicializar(3);
        }
        ...
    }

Salida:

Esto solo se imprime cuando la clase es cargada por un classloader
Valor inicial: 10
Valor cambio al invocar inicializar: 5
Valor cambio al invocar inicializar: 3

Para la segunda comparación mencionaremos que anteriormente (antes de Java 5) si era necesario hacer un calculo para inicializar una variable o constante estática solo se podía hacer mediante un metodo estático, con la introducción de bloques estáticos surgió una nueva alternativa de inicializar y realizar estos calculos, pero ahí no rádica la diferencia si no en el manejar excepciones.

Bloque estático vs Inicialización estática

import java.util.Random;

public class Ejemplo3 {

        static int numero;
       //numero = Ejemplo3.inicializar(100); //<-- Esto ocasionaría error de compilación

        static{
                try{
                        numero = Ejemplo3.inicializar(1000);
                } catch (IllegalNumberException e){    //Dentro de bloques estáticos se pueden manejar excepciones que originen los calculos.
                        e.printStackTrace();
                }
        }

        public static int inicializar(int numero) throws IllegalNumberException {
                if (numero > 100 || numero < 0){
                        throw new IllegalNumberException("El rango de tu numero debe de ser entre 0 y 100");
                }
                return new Random().nextInt(numero);
        }

        public static void main(String[] args) {
                System.out.println("Valor " + Ejemplo3.numero);
        }
}

class IllegalNumberException extends Exception {
       public IllegalNumberException(String msg){
                super(msg);
       }
}

Un dato importante es que puedes tener más de un bloque estático y estos se ejecutan en el orden de aparicion de la clase o interface como se muestra a continuación:

public class Ejemplo4{

    static{
         System.out.println("DOS");
    }

    static{
         System.out.println("UNO");
    }

   

    public static void main(String [] args){
         
    }  

    static{
         System.out.println("TRES");
    }

}

Salida:

DOS
UNO
TRES

Usos comunes:

1.-Cargar drivers o elementos a un namespace.
2.-Realizar calculos y/o asignaciones que solo se ejecutaran una sola vez.
3.-Trazado de errores (Logger).

Ventajas:

1.-Puedes ejecutar asignaciones a constantes y variables que requieran la ejecución de algún calculo sin la necesidad de crear una instancia.
2.-Si el código que utilizas para inicializar una constante o variable estática causa excepciones, las puedes manejar en bloques try-catch sin la necesidad de usar metodos estáticos o de instancia.

Limitaciones o desventajas:

1.-El tamaño de los bloques estáticos no debe exceder los 64kb.
2.-No se pueden lanzar excepciones checadas.
3.-No se puede usar la palabra reservada this debido a que no hay una instancia.
4.-No se puede usar la palabra reservada super debido a que no hay una instancia.
5.-No se puede regresar ningun valor o tipo.
6.-Es complicado hacer pruebas a los bloques estáticos.

Sin más que agregar me despido, hasta la proxima, ya saben si tienen algo más que aportar al tema se los agradecería.

Saludos.

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

JLS

Los bloques estáticos se describen en la sección §8.7 dentro de The Java Language Specification, Java SE 8 Edition.

Los bloques estáticos existen

Los bloques estáticos existen desde el inicio del lenguaje.

Por ejemplo esta copia no actualizada de la especificación del lenguaje ya los menciona: http://titanium.cs.berkeley.edu/doc/java-langspec-1.0/

Por cierto en Java lo que lleva el modificador "static" es en realidad: "de clase" (en contraposición con "de instancia"), por ejemplo variables de clase y métodos de clase. Es curioso en la spec a estos bloques si les llama inicializadores estáticos.

Imagen de Cid

Ok me debi confundir

@OscarRyz creo que me confundi con el dato que mencione parece ser que algún día leí uno de los manuales de Sun donde especificaba una nota que indicaba algo así "since JDK 5" pero ya me acorde que no era en la parte de bloques estáticos si no en la de los enhanced enums, bueno es que ese capitulo abarcaba varias cosas, en fin yo no los había usado mucho y pense que eran nuevos, siempre se aprende algo más, cambiare el post para corregir mi error.

Saludos.

¡Psst! Oye, Cid...

¡Psst! Oye, Cid... Tal vez quieras ver Java Programming Language Enhancements. Desde J2SE 1.4 a Java SE 8. ¡Por si sirve de algo! ;-)

@jpaul Esta bueno el link,

@jpaul Esta bueno el link, precisamente estaba buscando algo así.

@SrCid El mejor uso que encuentro de los inicializadores estáticos es el del ejemplo que pones donde se necesita manejar una excepción. +1

Imagen de Cid

Gracias @jpaul

Excelente ayuda, como siempre envías buenos recursos e información.

Saludos.

Imagen de julgo

otro uso común que se les da

otro uso común que se les da es para inicializar un singleton de manera eager