Como una variable estática es accesible antes de la declaración?
-
02-10-2019 - |
Pregunta
public class Main {
static int x = Main.y;
// static int x = y; //Not allowed; y is not defined
static int y = x;
public static void main(String[] args) {
System.out.println(x);//prints 0
}
}
¿Cómo es que se me permite el uso y a través de la clase, pero no directamente?
Cuando se define y?
Solución
Las reglas precisas que rigen referencia adelante a variables de clase se describe en la sección §8.3.2.3 de los JLS:
8.3.2.3 Restricciones en el uso de campos durante la inicialización
La declaración de un miembro necesita aparecerá textualmente antes de su uso sólo si el miembro es una instancia (Respectivamente
static
) Campo de una clase o interfaz C y todo el siguientes condiciones se cumplen:
- El uso se produce en una instancia (respectivamente
static
) Variable inicializador de C o en una instancia (Respectivamentestatic
) inicializador de C.- El uso no es en el lado izquierdo de una asignación.
- El uso es a través de un simple nombre.
- C es la clase más interna o interfaz que encierra el uso.
Se produce un error de tiempo de compilación si cualquiera de los cuatro requisitos anteriores no son Met.
Esto significa que un error de tiempo de compilación resultados del programa de prueba:
class Test { int i = j; // compile-time error: incorrect forward reference int j = 1; }
mientras que los siguientes compila ejemplo sin error:
class Test { Test() { k = 2; } int j = 1; int i = j; int k; }
a pesar de que el constructor (§8.8) para la prueba se refiere a la cuerpo k que se declara tres líneas más tarde.
Estas restricciones están diseñadas para captura, en tiempo de compilación, circular o inicializaciones mal formado de otra manera. Por lo tanto, los dos:
class Z { static int i = j + 2; static int j = 4; }
y
class Z { static { i = j + 2; } static int i, j; static { j = 4; } }
resultado de errores en tiempo de compilación. Accesos por métodos no se comprueban en De esta manera, por lo que:
class Z { static int peek() { return j; } static int i = peek(); static int j = 1; } class Test { public static void main(String[] args) { System.out.println(Z.i); } }
produce la salida:
0
porque la variable de inicialización para i utiliza el método de la clase vistazo a acceder el valor de la variable j antes de j se ha inicializado por su variable inicializador, momento en el que todavía tiene su valor por defecto (§4.12.5) .
Otros consejos
Yo asumiría que mediante el uso de la clase, el compilador aplazaría en busca de la variable hasta que la clase se había completado, por lo que encuentra y, pero si lo que lo define como el comentario que aún no está definido por lo que falla
Las variables estáticas se definen en orden de declaración de la clase, durante la carga de clases. Cuando la JVM carga la clase Main
, se definirá x
, y
entonces. Es por eso que no se puede utilizar directamente y
al inicializar x
, se crea algo que se llama un delantero de referencia , que hace referencia a una variable no definida en la actualidad, y eso es ilegal que el compilador.
Cuando se utiliza Main.y
, creo que sucede lo siguiente:
- carga
Main
,x
inicialización se llama - Cuando se define
x
ser iguales aMain.y
, el compilador ve una referencia a una clase, por lo que va a terminar definiendox
al valor actual de lay
miembro de la claseMain
. Se trata este caso como siMain
era una clase diferente.
Tenga en cuenta que en este caso, al inicializar x
, y
ha definido no ser por el momento. Así x
tendrá un valor de 0
.
Usted no está autorizado a hacerlo, ya que no tiene sentido. La única interpretación posible es que y se inicializa a cero, y ya tiene dos formas de decir eso. Usted no necesita esto.
Tal vez el compilador crea las referencias de las variables estáticas con valores por defecto con la clase en la pila, cuando se crea y luego asigna los valores previstos.