Domanda

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
    }
}

Come mai mi è permesso di utilizzare y attraverso la classe, ma non direttamente?

Quando viene definito y?

È stato utile?

Soluzione

Le norme precise di riferimento ora di variabili di classe sono descritti nella sezione §8.3.2.3 dei JLS:

  

8.3.2.3 Restrizioni per l'uso di campi durante l'inizializzazione

     

La dichiarazione di un membro deve   comparire testualmente prima del suo utilizzo   solo se l'elemento è un'istanza   (Rispettivamente static) campo di una classe   o interfaccia C e tutti i   seguenti condizioni:

     
      
  • L'utilizzo avviene in un'istanza (rispettivamente static) variabile   inizializzatore di C o in un'istanza   (Rispettivamente static) inizializzatore di   C.
  •   
  • L'utilizzo non è sul lato sinistro di una cessione.
  •   
  • L'utilizzo avviene tramite un semplice nome.
  •   
  • C è la classe più interno o interfaccia racchiude l'utilizzo.
  •   
     

Un errore di compilazione si verifica se una delle   i quattro requisiti di cui sopra non sono   MET.

     

Ciò significa che un errore di compilazione   risultati del programma di test:

  class Test {
      int i = j;  // compile-time error: incorrect forward reference
      int j = 1;
  }
     

, mentre i seguenti esempi di compilazioni   senza errori:

  class Test {
      Test() { k = 2; }
      int j = 1;
      int i = j;
      int k;
  }
     

anche se il costruttore    (§8.8) per la prova si riferisce alla   campo k dichiarata tre linee   più tardi.

     

Queste restrizioni sono progettati per   cattura, al momento della compilazione, circolare o   altrimenti deforme inizializzazioni.   Così, sia:

class Z {
  static int i = j + 2; 
  static int j = 4;
}
     

e

class Z {
  static { i = j + 2; }
  static int i, j;
  static { j = 4; }
}
     

risultato in errori di compilazione.   Accessi con metodi non vengono controllati in   in questo modo, così:

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 reazione:

0
     

perché l'inizializzazione variabile per i   utilizza il metodo della classe peek per l'accesso   il valore della variabile prima j j   è stato inizializzato dal suo variabile   inizializzatore, a quel punto ancora   ha il suo valore predefinito (§4.12.5) .

Altri suggerimenti

presumo che utilizzando la classe, il compilatore sarebbe rinviare alla ricerca per la variabile fino a quando la classe era completa, in modo che trova y, ma se proprio lo definiamo come il commento non è ancora definito in modo non riesce

Le variabili statiche sono definiti in ordine di dichiarazione della classe, durante le lezioni di carico. Quando la JVM caricherà la classe Main, sarà definita x, y poi. Ecco perché non è possibile utilizzare direttamente y durante l'inizializzazione x, è creare qualcosa che è chiamato un di riferimento in avanti , si fa riferimento a una variabile non attualmente definito, e che è illegale per il compilatore.

Quando si utilizza Main.y, credo che accade quanto segue:

  • carico Main, l'inizializzazione x si chiama
  • Quando si definisce x di essere uguali a Main.y, il compilatore vede un riferimento a una classe, in modo che si concluderà definire x al valore corrente del y membro della Main di classe. Si tratta questo caso, come se fosse Main una classe diversa.

Si noti che in questo caso, durante l'inizializzazione x, y ha non può essere definito per il momento. Così x avrà un valore di 0.

Non sei autorizzato a farlo perché è privo di significato. L'eventuale unica interpretazione è che y è inizializzato a zero, e hai già due modi di dire questo. Non hai bisogno di questo.

Forse il compilatore crea i riferimenti delle variabili statiche con i valori di default con la classe nello stack, quando viene creato e quindi assegna i valori forniti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top