tony r
¿Cuándo se inicializan los campos estáticos? Si nunca instalo una clase, pero accedo a un campo estático, ¿se llaman TODOS los bloques estáticos y métodos estáticos privados utilizados para instanciar campos estáticos privados (en orden) en ese instante?
¿Qué pasa si llamo a un método estático? ¿También ejecuta todos los bloques estáticos? ¿Antes del método?
esteban c
La inicialización estática de una clase normalmente ocurre inmediatamente antes de que ocurra uno de los siguientes eventos por primera vez:
- se crea una instancia de la clase,
- se invoca un método estático de la clase,
- se asigna un campo estático de la clase,
- se utiliza un campo estático no constante, o
para una clase de nivel superior, se ejecuta una declaración de afirmación anidada léxicamente dentro de la clase1.
Ver JLS 12.4.1.
También es posible forzar la inicialización de una clase (si aún no se ha inicializado) usando Class.forName(fqn, true, classLoader)
o la forma corta Class.forName(fqn)
¿Cuándo ocurre la inicialización de clase estática?
Véase más arriba.
¿Cuándo se inicializan los campos estáticos?
Como parte de la inicialización de clases estáticas; véase más arriba.
Si nunca instalo una clase, pero accedo a un campo estático, ¿se llaman TODOS los bloques estáticos y métodos estáticos privados utilizados para instanciar campos estáticos privados (en orden) en ese instante?
Sí. (Módulo que nada es verdaderamente instantáneo.)
¿Qué pasa si llamo a un método estático? ¿También ejecuta todos los bloques estáticos? ¿Antes del método?
Si y si.
Tenga en cuenta que es posible construir código donde se puede observar el predeterminado inicializado valor de un campo estático.
1: el punto final estaba presente en el JLS para Java 6 a Java 8, pero aparentemente era un error en la especificación. Finalmente se corrigió en Java 9 JLS: ver código fuente.
-
Sin embargo, hay una trampa común. Primitivos y
String
s son sustituidos y no referenciados. Si haces referencia a unclass Other { public static final int VAL = 10; }
de alguna claseMyClass { private int = Other.VAL; }
la claseOther
no se cargará. En su lugar, el compilador simplemente sustituirá el campo final en el momento de la compilación.–Rafael Winterhalter
28 de octubre de 2013 a las 9:45
-
@RafaelWinterhalter – sí … ese es el constante caso de campo estático.
– Esteban C.
14 de diciembre de 2015 a las 3:03
-
@RafaelWinterhalter, esto no es cierto para todas las primitivas o
String
variables, solo aquellas inicializadas por una expresión constante.– Lew Bloch
23 de mayo de 2017 a las 0:54
-
Sí, y el campo ni siquiera necesita ser
static
mientras que este es un caso común.–Rafael Winterhalter
23 de mayo de 2017 a las 5:40
-
@RafaelWinterhalter pero cuando el campo no está
static
necesita una referencia a una instancia de él (el compilador incrustará unnull
-verifique incluso cuando use el valor constante después), por lo que leer un no-static
el campo constante no desencadenará una inicialización de clase, pero la inicialización ya sucedió de todos modos, cuando se creó la instancia (si no antes)– Holger
8 de abril de 2022 a las 9:19
naikus
Los campos estáticos se inicializan durante el inicialización “fase” de la carga de clases (carga, enlace e inicialización) que incluye inicializadores estáticos e inicializaciones de sus campos estáticos. Los inicializadores estáticos se ejecutan en un orden textual como se define en la clase.
Considere el ejemplo:
public class Test {
static String sayHello() {
return a;
}
static String b = sayHello(); // a static method is called to assign value to b.
// but its a has not been initialized yet.
static String a = "hello";
static String c = sayHello(); // assignes "hello" to variable c
public static void main(String[] arg) throws Throwable {
System.out.println(Test.b); // prints null
System.out.println(Test.sayHello()); // prints "hello"
}
}
El Test.b imprime null
porque cuando el sayHello
fue llamada en ámbito estático, la variable estática a
no fue inicializado.
-
Estrictamente hablando, la inicialización no es una “fase” de la carga de clases. De hecho, algunas clases puede cargarse pero nunca inicializarse si la aplicación no los utiliza.
– Esteban C.
17 de agosto de 2010 a las 4:51
-
@Stephen C Tienes razón, lo usé por falta de un término mejor, tal vez lo citaré.
– naikus
17 de agosto de 2010 a las 5:09
-
@StephenC, ¿eso significa que mientras se lleva a cabo la carga de Clase, asigna memoria a variables estáticas (y métodos) pero esas variables estáticas no se inicializan con los valores proporcionados en el código? porque aquí parece que cuando b->sayHello()->a, ‘a’ está en la memoria pero aún no se le ha asignado un valor.
– Shabbir Ensayo
6 de febrero de 2018 a las 7:36
-
Básicamente sí.
– Esteban C.
6 de febrero de 2018 a las 8:09
-
@StephenC por favor, ¿podría dar algunos detalles? Como sé, en la fase de vinculación asigna memoria para variables estáticas y les asigna un valor predeterminado. Luego, en la fase de inicialización, les asigna valores originales. En este ejemplo,
b
es nulo, porque en la fase de inicialización los bloques estáticos se ejecutan de padre a hijo y de arriba a abajo.– Hayk Mkrtchyan
24 de enero de 2022 a las 10:41
Sí, todos los inicializadores estáticos se ejecutan antes de acceder a la clase por primera vez. Si fuera de otra manera, lo llamaría un error.
-
Hay formas de referirse a una clase sin inicializarla.
– Lew Bloch
23 de mayo de 2017 a las 0:56
Similar para bloques de inicializador estático: stackoverflow.com/questions/2007666/…
– Ciro Santilli OurBigBook.com
23 de marzo de 2015 a las 9:04