Me pregunto cuándo se inicializan las variables estáticas a sus valores predeterminados. ¿Es correcto que cuando se carga una clase, se crean (asignan) variables estáticas, luego se ejecutan los inicializadores estáticos y las inicializaciones en las declaraciones? ¿En qué momento se dan los valores predeterminados? Esto conduce al problema de la referencia hacia adelante.
También, 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 tercer punto.
java
static
initialization
Ankit
fuente
fuente
Respuestas:
De Ver métodos de variables estáticas de Java :
Las variables de instancia y clase (estáticas) se inicializan automáticamente a los valores predeterminados estándar si no las inicializa intencionalmente. Aunque las variables locales no se inicializan automáticamente, no puede compilar un programa que no pueda inicializar una variable local o asignar un valor a esa variable local antes de que se utilice.
Lo que el compilador realmente hace es producir internamente una rutina de inicialización de una sola clase que combina todos los inicializadores de variables estáticas y todos los bloques de código de inicializadores estáticos, en el orden en que aparecen en la declaración de clase. Este único procedimiento de inicialización se ejecuta automáticamente, una sola vez, cuando la clase se carga por primera vez.
En caso de clases internas , no pueden tener campos estáticos
Consulte JLS 8.1.3 Clases internas e instancias adjuntas
final
Los campos en Java se pueden inicializar por separado de su lugar de declaración, sin embargo, no puede ser aplicable a losstatic final
campos. 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
static
variables asociadas con el tipo, en lugar de una asociada con cada instancia del tipo, como ocurre con las variables de instancia y si intentamos inicializar elz
tipostatic final
dentro del constructor, intentará reinicializar elstatic final
campo de tipo.z
porque el constructor se ejecuta en cada instanciación de la clase que no debe ocurrir enfinal
campos estáticos .fuente
In case of static inner classes, they can not have static fields
parece un error tipográfico. Las clases internas no son estáticas.Ver:
El último en particular proporciona pasos de inicialización detallados que detallan cuándo se inicializan las variables estáticas y en qué orden (con la advertencia de que
final
las variables de clase y los campos de interfaz que son constantes en tiempo de compilación se inicializan primero).No estoy seguro de cuál es tu pregunta específica sobre el punto 3 (¿asumiendo que te refieres al anidado?). La secuencia detallada indica que esto sería una solicitud de inicialización recursiva, por lo que continuará la inicialización.
fuente
Los campos estáticos se inicializan cuando el cargador de clases carga la clase. Los valores predeterminados se asignan en este momento. Esto se hace en el orden en que aparecen en el código fuente.
fuente
El orden de inicialización es:
Los detalles del proceso se explican en el documento de especificación de JVM .
fuente
variable estática
fuente
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 volvamos a inicializar la clase:
obj
se hace una referencia a un nuevo objeto real, y ya está.Si esto fue compensado por una declaración como: el
MyClass mc = new MyClass();
espacio para una nueva instancia de MyClass se asigna nuevamente (y la referencia se coloca enmc
). El constructor se ejecuta de nuevo y se imprime de nuevoobj
, que ahora no es nulo.El verdadero truco aquí es que cuando usas
new
, como en,WhatEverItIs weii = new WhatEverItIs( p1, p2 );
weii
inmediatamente se le da una referencia a un poco de memoria anulada. La JVM luego continuará para inicializar valores y ejecutará el constructor. Pero si de alguna manera hace referenciaweii
antes de que lo haga, al hacer referencia a él desde otro hilo o al hacer referencia a la inicialización de la clase, por ejemplo, está viendo una instancia de clase llena de valores nulos.fuente
La variable estática se puede inicializar de las siguientes tres formas, como sigue, elija la que desee
o puede hacerlo haciendo un bloque estático, por ejemplo:
static { // whatever code is needed for initialization goes here }
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 } }
fuente