java inheritance constructor static-block

java - ¿En qué orden se ejecutan los bloques estáticos y los bloques de inicialización cuando se usa la herencia?



inheritance constructor (10)

Tengo dos clases, padre e hijo

public class Parent { public Parent() { System.out.println("Parent Constructor"); } static { System.out.println("Parent static block"); } { System.out.println("Parent initialisation block"); } } public class Child extends Parent { { System.out.println("Child initialisation block"); } static { System.out.println("Child static block"); } public Child() { System.out.println("Child Constructor"); } public static void main(String[] args) { new Child(); } }

La salida del código anterior será

Parent static block Child static block Parent initialization block Parent Constructor Child initialization block Child Constructor

¿Por qué Java ejecuta el código en ese orden? ¿Cuáles son las reglas que determinan el orden de ejecución?


Aprendo visualmente, así que aquí hay una representación visual del orden, como un SSCCE:

public class Example { static { step(1); } public static int step_1 = step(2); public int step_6 = step(6); public Example() { step(8); } { step(7); } // Just for demonstration purposes: public static int step(int step) { System.out.println("Step " + step); return step; } } public class ExampleSubclass extends Example { { step(9); } public static int step_3 = step(3); public int step_10 = step(10); static { step(4); } public ExampleSubclass() { step(11); } public static void main(String[] args) { step(5); new ExampleSubclass(); step(12); } }

Esto imprime:

Step 1 Step 2 Step 3 Step 4 Step 5 Step 6 Step 7 Step 8 Step 9 Step 10 Step 11 Step 12

Tenga en cuenta que el orden de las partes static importa; mira atrás en la diferencia entre el orden de las cosas static del Example y las de ExampleSubclass .

También tenga en cuenta que el bloque de inicialización de la instancia siempre se ejecuta antes del constructor, sin importar el orden. Sin embargo, el orden sí importa entre un bloque de inicialización y un inicializador de campo.


El bloque estático en java se ejecuta antes del método principal. Si declaramos un bloque Estático en clase java, se ejecutará cuando se cargue la clase. Esto se inicializa con las variables estáticas. Se usa principalmente en JDBC. El bloque estático en java se ejecuta cada vez que se carga una clase. Esto también se conoce como bloque de inicialización estática. El bloque estático en Java se inicializa cuando la clase se carga en la memoria, significa cuando JVM lee el código de bytes. La inicialización puede ser cualquier cosa; puede ser una inicialización variable o cualquier otra cosa que deba ser compartida por todos los objetos de esa clase. El bloque estático es un bloque de código normal encerrado entre llaves {} y está precedido por palabra clave estática.

por lo que el bloque estático se ejecuta primero.

Bloques de inicialización de instancia: se ejecuta cada vez que se crea la instancia de la clase.

entonces el siguiente bloque de inicialización se ejecuta cuando se crea la instancia de la clase.

entonces constructor ejecutado


El bloque estático se ejecuta cuando una clase se carga en JVM. Mientras que el bloque de inicio se copia en el Constructor, cuyo objeto se creará y se ejecutará antes de la creación del objeto.


Esto es lo que encontré mientras me preparaba para una certificación.

Mientras ejecutamos una clase, ocurre la primera inicialización de bloques estáticos / variables estáticas. Si hay varios bloques estáticos allí, los ejecutará en el orden en que aparecen,

A continuación, ejecutará los bloques de inicio / inicialización de la variable de instancia. Si hay múltiples bloques de inicio / inicialización variable, se ejecutará en el orden en que aparece,

Luego mirará en el constructor.


Hay varias reglas en juego

  • los bloques estáticos siempre se ejecutan antes de que se cree el objeto, de modo que es por eso que ve mensajes de impresión de ambos padres y bloques estáticos secundarios
  • ahora, cuando llamas al constructor de la subclase (hijo), este constructor llama implícitamente a super(); antes de ejecutar su propio constructor El bloqueo de inicialización entra en juego incluso antes de la llamada del constructor, por eso es que se llama primero. Entonces, ahora se creó su padre y el programa puede continuar creando una clase para niños que se someterá al mismo proceso.

Explicaciones

  1. El bloque estático del elemento primario se ejecuta primero porque se carga primero y se llaman bloques estáticos cuando se carga la clase.

Primero, ejecute la clase secundaria solamente (comente la cláusula extender) para ver el flujo simple.

segundo: ir al bloque Estático vs. bloque inicializador en Java? y lea la respuesta aceptada allí.

Editar:

  1. La ejecución ocurre en el modo SIC - Static, (no estático) Initializer & Constructor.
  2. (No estático) Inicializador se copian en cada constructor - En la parte superior! (por lo tanto, líneas 3/4/5/6)
  3. Antes de inicializar una clase, se debe inicializar su superclase directa - http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 (por lo tanto, el bloque estático principal aparece primero) .

Sería muy útil detectar el proceso de construcción de objetos con un debuger paso a paso, teniendo una vista en la que pueda ver cómo su objeto se mueve a través de las fases. Encontré esto muy útil para aclarar la perspectiva desde un punto de vista más elevado. Eclipse puede ayudarlo con su paso de depuración en la función.


Solo quería compartir mis hallazgos. Leí en una de las respuestas en otro hilo que los bloques estáticos se ejecutan primero antes de los campos estáticos, lo que no es correcto. Depende de qué viene primero, campo estático o bloque estático. Echa un vistazo al código a continuación. Tratará de poner las cosas en perspectiva.

  1. JVM busca una clase que tenga un vacío público estático principal (String args []) para que pueda cargar esa clase.
  2. Luego inicializa campos estáticos de esta clase (si vienen antes de bloques estáticos). Estos campos pueden llamar a métodos estáticos de esta clase u otra. Si llaman al método estático de esta clase, entonces ese método se sirve. Si llaman al método estático de otra clase, entonces los campos estáticos o bloques de esa clase (dependiendo de cuál viene primero) se inicializan primero, entonces se sirve esta llamada a método.
  3. Luego, se mueve a bloques estáticos.
  4. Vuelve al método principal.

    class TestLab { static int method(String a) { System.out.println("in static method of TestLab" + " Coming from " + a); System.out.println("b is " + b); return 6; } static int a = method("Line 11"); static int b = 7; TestLab() { System.out.println("Inside test lab constructor"); } static { System.out.println("In static block of TestLab"); } } public class Test1 { public static void main(String[] args) { System.out.println("inside main method of Test 1"); int a = TestLab.method("Line 26"); } // static Test ref=new Test(); Test1() { System.out.println("Default Constructor of Test1"); } { System.out.println("In instance block of Test1"); } static int d = TestLab.method("Line 37"); static int e = methodOfTest1(); static { System.out.println("In Static Block of Test1"); } static int methodOfTest1() { System.out.println("inside static method:mehtodOfTest1()"); return 3; } }

Aquí está el resultado:

in static method of TestLab Coming from Line 11 b is 0 In static block of TestLab in static method of TestLab Coming from Line 37 b is 7 inside static method:mehtodOfTest1() In Static Block of Test1 inside main method of Test 1 in static method of TestLab Coming from Line 26 b is 7


el flujo de control es-

bloque estático -> Bloque de inicialización -> y finalmente Constructor.

bloque estático -> Este bloque estático se ejecutará una sola vez cuando el control llegue a la clase. (JVM Cargar esta clase)

Bloque de inicialización -> Este bloque de inicialización se ejecutará cada vez que se cree un nuevo objeto para la clase (se ejecutará a partir de la segunda instrucción del constructor y luego de las declaraciones del constructor; recuerde que la primera declaración del constructor será Super () / this () )

Constructor -> Esto se obtendrá siempre que se cree un nuevo objeto.


  • Los bloques de inicio estáticos se ejecutan en el momento de la carga de la clase.
  • En la jerarquía de clases, el orden para la ejecución de bloques de inicio estáticos comenzará desde la clase de nivel superior.
  • En una clase, el orden para la ejecución del bloqueo estático es de arriba hacia abajo.
  • La regla anterior se aplica independientemente de dónde esté presente el bloque estático dentro de la clase.

(En su código, los bloques estáticos primarios se ejecutarán primero y luego los bloques estáticos de la clase hija).

  • Los bloques de inicio de instancia se ejecutarán después de la llamada al super (); en el constructor
    • Siempre super (); es la primera declaración en un constructor predeterminado.

En tu código cuando creas un objeto Child:

  • El constructor predeterminado de la clase Child se ejecuta.
  • Llamará al super (); constructor.
  • Luego se ejecuta el constructor de la superclase.
  • La clase Parent ejecutará su super (); llamada.
  • Después de eso, se ejecutan los bloques de instancia init en la clase Parent. (De arriba a abajo).
  • Luego se ejecuta el código dentro del constructor (si hay alguno).
  • Luego regresará a la clase Child y ejecutará los bloques init de la instancia de la clase Child.
  • Finalmente se ejecuta el código en el constructor hijo (si existe).