Inicializador estático en Java

Mi pregunta es sobre un uso particular de palabra clave estática. Es posible usar palabra clave static para cubrir un bloque de código dentro de una clase que no pertenece a ninguna función. Por ejemplo, las siguientes comstackciones de 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 palabra clave static se queja porque la variable a es final . Sin embargo, es posible eliminar palabras clave final y static y hacer que se compile.

Es confuso para mí en ambos sentidos. ¿Cómo se supone que tengo 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?

    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 elimina static de int a , se convierte en una variable de instancia a la que no puede acceder desde el bloque de inicializador estático. Esto no comstackrá con el error “la variable no estática a no se puede referenciar desde un contexto estático”.

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

    Uff! ¿Qué es el inicializador estático?

    El inicializador estático es un bloque de código static {} 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 la máquina virtual cuando se llama a la clase.
    • No se admiten declaraciones de return .
    • No se admiten argumentos.
    • No this o super son compatibles.

    Hmm, ¿dónde puedo usarlo?

    Se puede usar en cualquier lugar donde te sientas bien 🙂 así de simple. Pero veo que la mayoría de las veces se usa cuando se hace una conexión de base de datos, API init, Logging y etc.

    ¡No solo ladres! ¿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 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."); } } 

    ¿¿¿Salida???

    Inicializador estático interno.

    manzana

    naranja

    Pera

    Finalizar el inicializador estático.

    Método Principal Interior.

    ¡Espero que esto ayude!

    El bloque static es un “inicializador estático”.

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

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

     class JNIGlue { static { System.loadLibrary("foo"); } } 

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

    Salida:

    inicializador estático llamado

    inicializador de instancia llamado

    constructor llamado

    inicializador de instancia llamado

    constructor llamado

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

    El inicializador de instancia anterior contiene una instrucción println. Para entender cómo funciona, podemos tratarlo como una statement 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 variable de instancia son prácticamente lo mismo.

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

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

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

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

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

    Otro caso en el que los inicializadores de instancias son útiles son las clases internas anónimas, que no pueden declarar constructores en absoluto. (¿Será este un buen lugar para ubicar 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, los inicializadores de instancias son necesarios para ejecutar cualquier tipo de expresiones en el momento de la construcción.

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

    No escribirás código en un bloque estático que deba invocarse en cualquier parte de tu progtwig. Si se va a invocar el propósito del código, debe colocarlo en un método.

    Puede escribir bloques de inicializador estáticos para inicializar variables estáticas cuando se carga la clase, pero este código puede ser más complejo.

    Un bloque de inicializador estático se parece a un método sin nombre, sin argumentos y sin tipo de devolución. Como nunca lo llamas, no necesita un nombre. La única vez que se llama es cuando la máquina virtual carga la clase.

    cuando un desarrollador utiliza un bloque de inicializador, el comstackdor de Java copia el inicializador en cada constructor de la clase actual.

    Ejemplo:

    el siguiente código:

     class MyClass { private int myField = 3; { myField = myField + 2; //myField is worth 5 for all instance } public MyClass() { myField = myField * 4; //myField is worth 20 for all instance initialized with this construtor } public MyClass(int _myParam) { if (_myParam > 0) { myField = myField * 4; //myField is worth 20 for all instance initialized with this construtor //if _myParam is greater than 0 } else { myField = myField + 5; //myField is worth 10 for all instance initialized with this construtor //if _myParam is lower than 0 or if _myParam is worth 0 } } public void setMyField(int _myField) { myField = _myField; } public int getMyField() { return myField; } } public class MainClass{ public static void main(String[] args) { MyClass myFirstInstance_ = new MyClass(); System.out.println(myFirstInstance_.getMyField());//20 MyClass mySecondInstance_ = new MyClass(1); System.out.println(mySecondInstance_.getMyField());//20 MyClass myThirdInstance_ = new MyClass(-1); System.out.println(myThirdInstance_.getMyField());//10 } } 

    es equivalente a:

     class MyClass { private int myField = 3; public MyClass() { myField = myField + 2; myField = myField * 4; //myField is worth 20 for all instance initialized with this construtor } public MyClass(int _myParam) { myField = myField + 2; if (_myParam > 0) { myField = myField * 4; //myField is worth 20 for all instance initialized with this construtor //if _myParam is greater than 0 } else { myField = myField + 5; //myField is worth 10 for all instance initialized with this construtor //if _myParam is lower than 0 or if _myParam is worth 0 } } public void setMyField(int _myField) { myField = _myField; } public int getMyField() { return myField; } } public class MainClass{ public static void main(String[] args) { MyClass myFirstInstance_ = new MyClass(); System.out.println(myFirstInstance_.getMyField());//20 MyClass mySecondInstance_ = new MyClass(1); System.out.println(mySecondInstance_.getMyField());//20 MyClass myThirdInstance_ = new MyClass(-1); System.out.println(myThirdInstance_.getMyField());//10 } } 

    Espero que los desarrolladores comprendan mi ejemplo.

    El bloque de código estático se puede utilizar para crear instancias o inicializar variables de clase (a diferencia de las variables de objeto). Entonces, declarar “a” estático significa que es solo uno compartido por todos los objetos de prueba, y el bloque de código estático inicializa “a” solo una vez, cuando se carga por primera vez la clase de prueba, sin importar cuántos objetos de prueba se creen.

    Una definición de locking estático de: palabra clave estática en java

    Un bloque estático es un bloque de instrucciones dentro de una clase Java que se ejecuta cuando una clase se carga por primera vez en la JVM, por ejemplo, se inicializa la primera vez que se hace referencia a la clase en el código.

    Normalmente, los bloques estáticos se utilizan para inicializar variables de clase estáticas, y son diferentes de los constructores en que los bloques estáticos se ejecutan solo una vez en la carga de clases y la inicialización por JVM mientras se llama al constructor cada vez que se crea una nueva instancia de la clase.

    PD: no puede usar variables de instancia ni invocar métodos de instancia dentro del bloque estático.

    Un ejemplo típico de uso de un bloque estático es cuando admite la recuperación de una instancia de Enum por su valor, para ello define un hashmap como una variable estática que asigna cada valor a su instancia de Enum correspondiente, el mapa se inicializa y se llena dentro de un estático bloquear antes de utilizar Enum en la aplicación.

     public enum ErrorCodes { BUSINESS_ERROR(100), SERVER_ERROR(500), NETWORK_ERROR(1000); private int errorCode; // This field maps each error code numeric value to a corresponding Enum instance. private static Map errorCodeByErrorNumber = new HashMap(); static { for (ErrorCodes errorCode : ErrorCodes.values()) { errorCodeByErrorNumber.put(errorCode.getErrorCode(), errorCode); } } private ErrorCodes(int errorCode) { this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } public static ErrorCodes getErrorCodeByNumber(Integer dayNumber) { return errorCodeByErrorNumber.get(dayNumber); } } 

    La palabra clave estática se puede usar con clase, variable, método y bloque. Los miembros estáticos pertenecen a la clase en lugar de a una instancia específica, esto significa que si haces que un miembro sea estático, puedes acceder a él sin ningún objeto. Ejemplo:

    Aquí tenemos un método estático myStatic (), podemos llamar a este método sin ningún objeto porque cuando hacemos un miembro estático se convierte en nivel de clase. Si eliminamos la palabra clave estática y la convertimos en no estática, debemos crear un objeto de la clase para llamarla

    Los miembros estáticos son comunes para todas las instancias (objetos) de la clase, pero los miembros no estáticos están separados para cada instancia de clase.

     class SimpleStaticExample { //static method static void myStatic() { System.out.println("my Static Method"); } public static void main(String[] args) { /* You can see that we are calling this * method without creating any object. */ myStatic(); } } 

    Salida: mi método estático