¿Cuándo se inicializan las variables estáticas?

Me pregunto cuándo las variables estáticas se inicializan a sus valores predeterminados. ¿Es correcto que cuando se carga una clase, se crean (asignan) vars estáticos, luego se ejecutan los inicializadores estáticos y las inicializaciones en las declaraciones? ¿En qué momento se dan los valores predeterminados? Esto lleva al problema de la referencia directa.

También, por favor, si puede explicar esto en referencia a la pregunta sobre ¿Por qué los campos estáticos no se inicializan a tiempo? y especialmente la respuesta dada por Kevin Brock en el mismo sitio. No puedo entender el 3er punto.

  • Es una variable que pertenece a la clase y no al objeto (instancia)
  • Las variables estáticas se inicializan solo una vez, al inicio de la ejecución.
  • Estas variables se inicializarán primero, antes de la inicialización de cualquier variable de instancia
  • Una sola copia para ser compartida por todas las instancias de la clase
  • El nombre de clase puede acceder directamente a una variable estática y no necesita ningún objeto. Ver Java Static Variable Methods .

Las variables de instancias y clases (estáticas) se inicializan automáticamente a los valores predeterminados estándar si no las inicializa deliberadamente. Aunque las variables locales no se inicializan automáticamente, no puede comstackr un progtwig que no puede inicializar una variable local ni asignar un valor a esa variable local antes de que se use.

Lo que el comstackdor realmente hace es producir internamente una rutina de inicialización de clase única que combine todos los inicializadores de variables estáticas y todos los bloques de código de inicializador estático, en el orden en que aparecen en la statement de clase. Este procedimiento de inicialización único se ejecuta automáticamente, solo una vez, cuando la clase se carga por primera vez.

En el caso de las clases internas , no pueden tener campos estáticos

Una clase interna es una clase anidada que no está explícita o implícitamente declarada static .

Las clases internas no pueden declarar inicializadores estáticos (§8.7) o interfaces de miembros …

Las clases internas no pueden declarar miembros estáticos, a menos que sean variables constantes …

Consulte JLS 8.1.3 Clases internas e instancias adjuntas

final campos final en Java se pueden inicializar por separado de su lugar de statement; sin embargo, esto no se puede aplicar a static final campos static final . Vea el ejemplo a continuación.

 final class Demo { private final int x; private static final int z; //must be initialized here. static { z = 10; //It can be initialized here. } public Demo(int x) { this.x=x; //This is possible. //z=15; compiler-error - can not assign a value to a final variable z } } 

Esto se debe a que solo hay una copia de las variables static asociadas con el tipo, en lugar de una asociada con cada instancia del tipo como con las variables de instancia, y si tratamos de inicializar z de tipo static final dentro del constructor, intentará reinicializar el campo de tipo static final z porque el constructor se ejecuta en cada instanciación de la clase que no debe ocurrir a los campos final estáticos.

Ver:

  • JLS 8.7, Inicializadores estáticos
  • JLS 12.2, carga de clases e interfaces
  • JLS 12.4, Inicialización de clases e interfaces

El último en particular proporciona pasos de inicialización detallados que explican cuándo se inicializan las variables estáticas, y en qué orden (con la advertencia de que las variables de clase final y los campos de interfaz que son constantes de tiempo de comstackción se inicializan primero).

No estoy seguro de cuál es su pregunta específica sobre el punto 3 (suponiendo que se refiera al nested). La secuencia detallada indica que esto sería una solicitud de inicialización recursiva, por lo que continuará la inicialización.

Los campos estáticos se inicializan cuando el cargador de clases carga la clase. Los valores predeterminados están asignados en este momento. Esto se hace en el orden en que aparecen en el código fuente.

El orden de inicialización es:

  1. Bloques de inicialización estática
  2. Bloques de inicialización de instancias
  3. Constructores

Los detalles del proceso se explican en el documento de especificación de JVM.

variable estática

  • Es una variable que pertenece a la clase y no al objeto (instancia)
  • Las variables estáticas se inicializan solo una vez, al comienzo de la ejecución (cuando el cargador de clases carga la clase por primera vez).
  • Estas variables se inicializarán primero, antes de la inicialización de cualquier variable de instancia
  • Una sola copia para ser compartida por todas las instancias de la clase
  • Se puede acceder directamente a una variable estática por el nombre de clase y no necesita ningún objeto

Comenzando con el código de la otra pregunta:

 class MyClass { private static MyClass myClass = new MyClass(); private static final Object obj = new Object(); public MyClass() { System.out.println(obj); // will print null once } } 

Una referencia a esta clase comenzará la inicialización. Primero, la clase se marcará como inicializada. Luego, el primer campo estático se inicializará con una nueva instancia de MyClass (). Tenga en cuenta que myClass recibe inmediatamente una referencia a una instancia de MyClass en blanco . El espacio está ahí, pero todos los valores son nulos. El constructor ahora se ejecuta e imprime obj , que es nulo.

Ahora volvemos a inicializar la clase: obj se hace referencia a un nuevo objeto real, y hemos terminado.

Si esto fue activado por una statement como: MyClass mc = new MyClass(); se asigna nuevamente el espacio para una nueva instancia de MyClass (y la referencia se coloca en mc ). El constructor se ejecuta nuevamente y vuelve a imprimir obj , que ahora no es nulo.

El verdadero truco aquí es que cuando usas new , como en WhatEverItIs weii = new WhatEverItIs( p1, p2 ); weii recibe inmediatamente una referencia a un poco de memoria anulada. La JVM continuará para inicializar valores y ejecutar el constructor. Pero si de alguna manera hace referencia a weii antes de que lo haga, al hacer referencia a ella desde otra secuencia o al hacer referencia a la inicialización de la clase, por ejemplo, está viendo una instancia de clase llena de valores nulos.

La variable estática se puede inicializar de las tres formas siguientes, y luego elija la que más le guste.

  1. puedes intializarlo en el momento de la statement
  2. o puede hacerlo haciendo bloque estático, por ejemplo: *

    static {// cualquier código que se necesite para la inicialización va aquí}

*

  1. Existe una alternativa a los bloques estáticos: puede escribir un método estático privado

 class name { public static varType myVar = initializeVar(); private static varType initializeVar() { // initialization code goes here } }