web-dev-qa-db-fra.com

Quand les variables statiques sont-elles initialisées?

Je me demande quand les variables statiques sont initialisées à leurs valeurs par défaut. Est-il exact que lorsqu'une classe est chargée, des vars statiques sont créés (alloués), puis des initialiseurs statiques et des initialisations dans les déclarations sont exécutés? À quel moment les valeurs par défaut sont-elles données? Cela pose le problème de la référence en aval.

Aussi, s'il vous plaît, si vous pouvez expliquer cela en référence à la question posée sur Pourquoi les champs statiques ne sont pas initialisés dans le temps? et en particulier la réponse donnée par Kevin Brock sur le même site. Je ne peux pas comprendre le 3ème point.

72
Ankit

De Voir Java Méthodes de variables statiques :

  • C'est une variable qui appartient à la classe et non à objecter (instance)
  • Les variables statiques ne sont initialisées qu'une seule fois, au début de l'exécution. Ces variables seront d'abord initialisées, avant l'initialisation des variables d'instance
  • Une seule copie à partager avec toutes les instances de la classe
  • Une variable statique est accessible directement par le nom de la classe et n’a besoin d’aucun objet.

Les variables d'instance et de classe (statiques) sont automatiquement initialisées sur les valeurs par défaut standard si vous ne parvenez pas à les initialiser volontairement. Bien que les variables locales ne soient pas automatiquement initialisées, vous ne pouvez pas compiler un programme qui ne parvient pas à initialiser une variable locale ou à affecter une valeur à cette variable locale avant son utilisation.

En réalité, le compilateur produit en interne une seule routine d'initialisation de classe qui combine tous les initialiseurs de variables statiques et tous les blocs de code d'initialisation statiques, dans l'ordre dans lequel ils apparaissent dans la déclaration de classe. Cette procédure d'initialisation unique est exécutée automatiquement, une fois seulement, lors du premier chargement de la classe.

Dans le cas de classes internes , elles ne peuvent pas avoir de champs statiques

Une classe interne est une classe imbriquée qui n'est pas explicitement ou implicitement déclarée static.

...

Les classes intérieures ne peuvent pas déclarer d'initialiseurs statiques (§8.7) ni d'interfaces membres ...

Les classes intérieures ne peuvent pas déclarer de membres statiques, sauf si elles sont des variables constantes ...

Voir JLS 8.1.3 Inner Classes et Inclus Closing

final les champs dans Java peuvent être initialisés séparément de leur lieu de déclaration, mais ne peuvent pas être appliqués à static final des champs. Voir l'exemple ci-dessous.

final class Demo
{
    private final int x;
    private static final int z;  //must be initialized here.

    static 
    {
        z = 10;  //It can be initialized here.
    }

    public Demo(int x)
    {
        this.x=x;  //This is possible.
        //z=15; compiler-error - can not assign a value to a final variable z
    }
}

En effet, il n’existe qu’une seule copie des variables static associées au type, et non une variable associée à chaque instance du type, comme pour les variables d’instance et si nous essayons d’initialiser z de type static final dans le constructeur, il tentera de réinitialiser le static final type champ z car le constructeur est exécuté à chaque instanciation de la classe qui ne doit pas se produire dans des champs _ final statiques.

60
Lion

Voir:

Le dernier en particulier fournit étapes d'initialisation détaillées qui indique quand les variables statiques sont initialisées et dans quel ordre (avec l'avertissement que final les variables de classe et les champs d'interface qui sont des constantes à la compilation sont initialisés en premier.)

Je ne suis pas sûr de votre question spécifique sur le point 3 (en supposant que vous vouliez dire le niché?). La séquence détaillée indique qu'il s'agirait d'une demande d'initialisation récursive afin de poursuivre l'initialisation.

14
Dave Newton

Les champs statiques sont initialisés lorsque la classe est chargée par le chargeur de classes. Les valeurs par défaut sont attribuées à ce moment. Ceci est fait dans l'ordre dans lequel ils apparaissent dans le code source.

8
Dave

L'ordre d'initialisation est:

  1. Blocs d'initialisation statiques
  2. Blocs d'initialisation d'instance
  3. Constructeurs

Les détails du processus sont expliqués dans le document JVM spécification .

7
Óscar López

variable statique

  • C'est une variable qui appartient à la classe et non à objecter (instance)
  • Les variables statiques ne sont initialisées qu'une seule fois, au début de l'exécution (lorsque le chargeur de charge charge la classe pour la première fois).
  • Ces variables seront d'abord initialisées, avant l'initialisation des variables d'instance
  • Une seule copie à partager avec toutes les instances de la classe
  • Une variable statique est accessible directement par le nom de la classe et ne nécessite aucun objet.
3
aleroot

En commençant par le code de l'autre question:

class MyClass {
  private static MyClass myClass = new MyClass();
  private static final Object obj = new Object();
  public MyClass() {
    System.out.println(obj); // will print null once
  }
}

Une référence à cette classe commencera l'initialisation. Premièrement, la classe sera marquée comme étant initialisée. Ensuite, le premier champ statique sera initialisé avec une nouvelle instance de MyClass (). Notez que myClass reçoit immédiatement une référence à une instance vide MyClass. L'espace est là, mais toutes les valeurs sont nulles. Le constructeur est maintenant exécuté et affiche obj, ce qui est null.

Revenons maintenant à l’initialisation de la classe: obj fait référence à un nouvel objet réel, et nous avons terminé.

Si cela était déclenché par une instruction du type: MyClass mc = new MyClass();, de nouveau espace est attribué pour une nouvelle instance de MyClass (et la référence placée dans mc). Le constructeur est à nouveau exécuté et affiche à nouveau obj, ce qui maintenant n'est pas nul.

Le vrai truc ici est que lorsque vous utilisez new, comme dans WhatEverItIs weii = new WhatEverItIs( p1, p2 );weii, une référence à un bit de mémoire annulée est immédiatement attribuée. La JVM initialise ensuite les valeurs et exécute le constructeur. Mais si vous faites référence à weiiavant c'est le cas - en le référençant depuis un autre thread ou en faisant référence à l'initialisation de la classe, par exemple - vous regardez une instance de classe rempli de valeurs nulles.

3
RalphChapin

La variable statique peut être initialisée des trois manières suivantes: choisissez celle que vous préférez

  1. vous pouvez l'initialiser au moment de la déclaration
  2. ou vous pouvez le faire en faisant un bloc statique, par exemple:

    static {
            // whatever code is needed for initialization goes here
        }
    
  3. Il existe une alternative aux blocs statiques - vous pouvez écrire une méthode statique privée

    class name {
        public static varType myVar = initializeVar();
    
        private static varType initializeVar() {
            // initialization code goes here
        }
    }
    
3
ajay verma