Question

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

Pourquoi je suis autorisé à utiliser la classe y creux, mais pas directement?

Quand y défini?

Était-ce utile?

La solution

Les règles précises avant référence aux variables de classe sont décrites dans la section §8.3.2.3 des JLS:

  

8.3.2.3 Restrictions sur l'utilisation des champs lors de l'initialisation

     

La déclaration d'un membre doit   apparaissent textuellement avant qu'il ne soit utilisé   que si le membre est une instance   (Respectivement static) champ d'une classe   ou de l'interface C et tous les   conditions suivantes sont satisfaites:

     
      
  • L'utilisation se produit dans une variable instance (respectivement static)   initialiseur de C ou dans une instance   (Respectivement static) initialiseur de   C.
  •   
  • L'utilisation est pas sur le côté gauche d'une affectation.
  •   
  • L'utilisation se fait par un simple nom.
  •   
  • C est la classe la plus interne ou de l'interface entourant l'utilisation.
  •   
     

Une erreur de compilation se produit si l'un des   les quatre exigences ci-dessus ne sont pas   Met.

     

Cela signifie qu'une erreur de compilation   les résultats du programme de test:

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

alors que les compiles exemple suivant   sans erreur:

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

même si le constructeur    (§8.8) pour le test se réfère à la   k champ qui est déclaré trois lignes   plus tard.

     

Ces restrictions sont destinées à   prise, au moment de la compilation, circulaire ou   autrement malformé initialisations.   Ainsi, à la fois:

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

et

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

résultat des erreurs de compilation.   Par des méthodes Accède ne sont pas vérifiées dans   De cette façon, donc:

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

produit la sortie:

0
     

parce que la initialiseur variable pour i   utilise la méthode de classe d'accès peek   la valeur de la variable j j avant   a été initialisé par sa variable   initialiseur, à quel point il encore   a sa valeur par défaut (§4.12.5) .

Autres conseils

Je suppose qu'en utilisant la classe, le compilateur reporterait la recherche de la variable jusqu'à ce que la classe était complète, il trouve y, mais si vous définissez tout comme le commentaire il n'est pas encore défini de sorte qu'il ne

Les variables statiques sont définies dans l'ordre de déclaration dans la classe, pendant le chargement de classe. Lorsque la machine virtuelle Java chargera sera définie la classe Main, x, y alors. Voilà pourquoi vous ne pouvez pas utiliser directement y lors de l'initialisation x, vous créez quelque chose qui est appelé référence avant , vous fait référence à une variable non définie actuellement, et c'est illégal pour le compilateur.

Lors de l'utilisation Main.y, je pense que ce qui suit se produit:

  • Vous chargez Main, l'initialisation de x est appelé
  • Lorsque vous définissez x être égaux à Main.y, le compilateur voit une référence à une classe, il mettra fin à la définition x à la valeur actuelle du y membre du Main de classe. Il traite ce cas comme si Main était une autre classe.

Notez que dans ce cas, lors de l'initialisation x, y a pas été définie pour le moment. Donc x aura une valeur de 0.

Vous n'êtes pas autorisé à le faire parce qu'il n'a pas de sens. L'interprétation possible est que y est initialisé à zéro, et vous avez déjà deux façons de dire que. Vous n'avez pas besoin de cela.

Peut-être que le compilateur crée les références des variables statiques avec des valeurs par défaut avec la classe dans la pile, lors de sa création et affecte ensuite les valeurs fournies.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top