¿Cuál es la diferencia entre un bloque de código de inicialización estático y no estático?

Resuelto Szere Dyeri asked hace 15 años • 9 respuestas

Mi pregunta es sobre un uso particular de la palabra clave estática. Es posible utilizar staticuna palabra clave para cubrir un bloque de código dentro de una clase que no pertenece a ninguna función. Por ejemplo, se compila el siguiente código:

public class Test {
    private static final int a;    
    static {
        a = 5;
        doSomething(a);
    }
    private static int doSomething(int x) {
        return (x+5);
    }
}

Si elimina la staticpalabra clave, se queja porque la variable aes final. Sin embargo, es posible eliminar las palabras clave finaly staticy compilarlas.

Es confuso para mí en ambos sentidos. ¿Cómo se supone que voy a tener una sección de código que no pertenece a ningún método? ¿Cómo es posible invocarlo? En general, ¿cuál es el propósito de este uso? O mejor, ¿dónde puedo encontrar documentación sobre esto?

Szere Dyeri avatar Dec 03 '08 03:12 Szere Dyeri
Aceptado

El bloque de código con el modificador estático significa un inicializador de clase ; sin el modificador estático, el bloque de código es un inicializador de instancia .

Los inicializadores de clase se ejecutan en el orden en que se definen (de arriba hacia abajo, al igual que los inicializadores de variables simples) cuando se carga la clase (en realidad, cuando se resuelve, pero eso es un tecnicismo).

Los inicializadores de instancia se ejecutan en el orden definido cuando se crea una instancia de la clase, inmediatamente antes de que se ejecute el código del constructor, inmediatamente después de la invocación del superconstructor.

Si lo elimina static, int ase convierte en una variable de instancia, a la que no puede acceder desde el bloque inicializador estático. Esto no se podrá compilar y aparecerá el error "No se puede hacer referencia a una variable no estática desde un contexto estático".

Si también lo elimina staticdel bloque inicializador, se convierte en un inicializador de instancia y, por lo tanto, int ase inicializa en la construcción.

Lawrence Dol avatar Dec 02 '2008 20:12 Lawrence Dol

¡Uf! ¿Qué es el inicializador estático?

El inicializador estático es un static {}bloque de código dentro de la clase Java y se ejecuta solo una vez antes de llamar al constructor o al método principal.

¡DE ACUERDO! Dime más...

  • es un bloque de código static { ... } dentro de cualquier clase java. y ejecutado por una máquina virtual cuando se llama a la clase.
  • No returnse admiten declaraciones.
  • No se apoyan argumentos.
  • No thiso superson compatibles.

Mmmm donde puedo usarlo?

Se puede usar en cualquier lugar donde te sientas bien :) así de simple. Pero veo que la mayor parte del tiempo se usa al realizar conexiones de bases de datos, inicio de API, registros, etc.

¡No te limites a ladrar! ¿Dónde está el ejemplo?

package com.example.learnjava;

import java.util.ArrayList;

public class Fruit {

    static {
        System.out.println("Inside Static Initializer.");

        // fruits array
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Orange");
        fruits.add("Pear");

        // print fruits
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
        System.out.println("End Static Initializer.\n");
    }

    public static void main(String[] args) {
        System.out.println("Inside Main Method.");
    }
}

¿¿¿Producción???

Inicializador estático interior.

Manzana

Naranja

Pera

Finalizar el inicializador estático.

Dentro del método principal.

Madan Sapkota avatar Mar 24 '2015 05:03 Madan Sapkota

El staticbloque es un "inicializador estático".

Se invoca automáticamente cuando se carga la clase y no hay otra forma de invocarla (ni siquiera a través de Reflection).

Personalmente, solo lo he usado al escribir código JNI:

class JNIGlue {
    static {
        System.loadLibrary("foo");
    }
}
Alnitak avatar Dec 02 '2008 20:12 Alnitak

Esto es directamente de http://www.programcreek.com/2011/10/java-class-instance-initializers/

1. Orden de Ejecución

Mira la siguiente clase, ¿sabes cuál se ejecuta primero?

public class Foo {
 
    //instance variable initializer
    String s = "abc";
 
    //constructor
    public Foo() {
        System.out.println("constructor called");
    }
 
    //static initializer
    static {
        System.out.println("static initializer called");
    }
 
    //instance initializer
    {
        System.out.println("instance initializer called");
    }
 
    public static void main(String[] args) {
        new Foo();
        new Foo();
    }
}

Producción:

inicializador estático llamado

inicializador de instancia llamado

constructor llamado

inicializador de instancia llamado

constructor llamado

2. ¿Cómo funciona el inicializador de instancias de Java?

El inicializador de instancia anterior contiene una declaración println. Para entender cómo funciona, podemos tratarlo como una declaración de asignación de variables, por ejemplo, b = 0. Esto puede hacer que sea más obvio de entender.

En lugar de

int b = 0, podrías escribir

int b;
b = 0;

Por lo tanto, los inicializadores de instancia y los inicializadores de variables de instancia son prácticamente iguales.

3. ¿Cuándo son útiles los inicializadores de instancias?

El uso de inicializadores de instancia es poco común, pero aún así puede ser una alternativa útil a los inicializadores de variables de instancia si:

  1. El código inicializador debe manejar excepciones.
  2. Realice cálculos que no se pueden expresar con un inicializador de variable de instancia.

Por supuesto, dicho código podría escribirse en constructores. Pero si una clase tuviera varios constructores, tendrías que repetir el código en cada constructor.

Con un inicializador de instancia, puede escribir el código una vez y se ejecutará sin importar qué constructor se utilice para crear el objeto. (Supongo que esto es sólo un concepto y no se usa con frecuencia).

Otro caso en el que los inicializadores de instancia son útiles son las clases internas anónimas, que no pueden declarar ningún constructor. (¿Será este un buen lugar para colocar una función de registro?)

Gracias a Derhein.

También tenga en cuenta que las clases anónimas que implementan interfaces [1] no tienen constructores. Por lo tanto, se necesitan inicializadores de instancia para ejecutar cualquier tipo de expresión en el momento de la construcción.

Alexei Fando avatar May 22 '2015 05:05 Alexei Fando

"final" garantiza que una variable debe inicializarse antes del final del código inicializador del objeto. Del mismo modo, "final estático" garantiza que una variable se inicializará al final del código de inicialización de clase. Omitir lo "estático" de su código de inicialización lo convierte en código de inicialización de objeto; por tanto su variable ya no satisface sus garantías.

DJClayworth avatar Dec 02 '2008 20:12 DJClayworth