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?

¿Fue útil?

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 (Respectivamente static) 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 a Main.y, el compilador ve una referencia a una clase, por lo que va a terminar definiendo x al valor actual de la y miembro de la clase Main. Se trata este caso como si Main 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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top