java - móviles - manual de programacion android pdf
Orden de inicialización de campos finales (2)
Aquí hay un código que llama al método estático Af () en la clase que aún no se ha inicializado. ¿Alguien puede explicar el comportamiento de este código en términos de JLS?
class A {
final static Object b = new B();
final static int S1 = 1;
final static Integer S2 = 2;
static void f() {
System.out.println(S1);
System.out.println(S2);
}
}
class B {
static {
A.f();
}
}
public class App
{
public static void main( String[] args )
{
A.f();
}
}
Salida:
1
null
1
2
Parece que este problema no pertenece a JLS
, pero tenemos trato con JVMS
.
En la etapa de Linking
antes del proceso de resolution
, hay un subestado de Preparation , que implica:
crear los campos estáticos para una clase o interfaz e inicializar dichos campos a sus valores predeterminados
y más:
Los inicializadores explícitos para campos estáticos se ejecutan como parte de la inicialización (§5.5), no de preparación
mientras que la initialization incluye:
La ejecución de cualquiera de las instrucciones de la Máquina Virtual Java nuevas.
La inicialización de tipos primitivos incluye escribir su valor inicial. Para los campos de tipo de referencia, su valor predeterminado es null
porque antes de la subestadial de Resolution jvm no "sabe" qué clase está asociada a un nombre de referencia simbólico apropiado de una clase.
Af()
en App.main()
desencadena la inicialización de la clase A
Todas las variables constantes son inicializadas. La única variable constante es S1
, que ahora es 1
.
Luego, los otros campos estáticos se inicializan en orden textual. b
es el primer campo, que activa la inicialización de la clase B
, que a su vez llama a Af()
. S2
es simplemente null
porque aún no está inicializado. La inicialización de b
está ahora completa. Por último, pero no menos importante, S2
se inicializa en el objeto Integer
2
.
S2
no es una variable constante porque no es del tipo primitivo int
sino del tipo de referencia Integer
. S2 = 2;
es una abreviatura de boxeo automático para S2 = Integer.valueOf(2);
.
Si un declarador en una declaración de campo tiene un inicializador de variable, entonces el declarador tiene la semántica de una asignación (§15.26) a la variable declarada.
[…]
Tenga en cuenta que
static
camposstatic
que son variables constantes (§4.12.4) se inicializan antes que otros camposstatic
(§12.4.2). Esto también se aplica en las interfaces (§9.3.1). Nunca se observará que tales campos tengan sus valores iniciales predeterminados (§4.12.5), incluso por programas tortuosos.
8.3.2. Inicialización de campo
Una variable constante es una variable
final
de tipo primitivo o tipoString
que se inicializa con una expresión constante (§15.28). Si una variable es constante o no, puede tener implicaciones con respecto a la inicialización de clase (§12.4.1), compatibilidad binaria (§13.1, §13.4.9) y asignación definida (§16 (Asignación definida)).
Una expresión constante es una expresión que denota un valor de tipo primitivo o una
String
que no se completa abruptamente y se compone utilizando solo lo siguiente:
- Literales de tipo primitivo y literales de tipo
String
[…]
Para cada clase o interfaz C, hay un bloqueo de inicialización único
LC
. La asignación de C aLC
se deja a discreción de la implementación de la Máquina Virtual de Java. El procedimiento para inicializar C es el siguiente:[…]
De lo contrario, registre el hecho de que el subproceso actual está realizando la inicialización del objeto
Class
para C y libereLC
.Luego, inicialice los campos
static
de C, que son variables constantes (§4.12.4, §8.3.2, §9.3.1).[…]
- A continuación, ejecute los inicializadores de variable de clase y los inicializadores estáticos de la clase, o los inicializadores de campo de la interfaz, en orden textual, como si fueran un solo bloque.
12.4.2. Procedimiento de Inicialización Detallado
Cada variable en un programa debe tener un valor antes de que se use su valor:
Cada variable de clase, variable de instancia o componente de matriz se inicializa con un valor predeterminado cuando se crea (§15.9, §15.10.2):
[…]
- Para todos los tipos de referencia (§4.3), el valor predeterminado es
null
.