web-dev-qa-db-fra.com

Quand l'initialisation de classe statique a-t-elle lieu?

Quand les champs statiques sont-ils initialisés? Si je n'instancie jamais une classe, mais que j'accède à un champ statique, TOUS les blocs statiques et les méthodes statiques privées utilisés pour instancier des champs statiques privés sont-ils appelés (dans l'ordre) à cet instant?

Et si j'appelle une méthode statique? Existe-t-il également tous les blocs statiques? Avant la méthode?

107
Tony R

L'initialisation statique d'une classe se produit normalement juste avant la première fois qu'un des événements suivants se produit:

  • une instance de la classe est créée,
  • une méthode statique de la classe est invoquée,
  • un champ statique de la classe est attribué,
  • un champ statique non constant est utilisé, ou
  • pour une classe de niveau supérieur, une instruction assert imbriquée lexicalement dans la classe est exécutée1.

Voir JLS 12.4.1 .

Il est également possible de forcer une classe à s’initialiser (si elle ne l’a pas déjà été) en utilisant Class.forName(fqn, true, classLoader) ou la forme abrégée Class.forName(fqn)


1 - Le dernier point était présent dans le JLS pour Java 6 à Java 8, mais il s'agissait apparemment d'une erreur dans la spécification. Il a finalement été corrigé dans le Java 9 JLS: voir source .

150
Stephen C

Les champs statiques sont initialisés pendant la initialisation "phase" du chargement de la classe (chargement, liaison et initialisation) qui inclut les initialiseurs statiques et les initialisations de ses champs statiques. Les initialiseurs statiques sont exécutés dans un ordre textuel tel que défini dans la classe.

Considérons l'exemple:

public class Test {

   static String sayHello()  {
      return a;
   }

   static String b = sayHello(); // a static method is called to assign value to b.
                                 // but its a has not been initialized yet.

   static String a = "hello";

   static String c = sayHello(); // assignes "hello" to variable c

    public static void main(String[] arg) throws Throwable {
         System.out.println(Test.b); // prints null
         System.out.println(Test.sayHello()); // prints "hello"
    }
}

Test.b imprime null car, lorsque la sayHello était appelée dans une portée statique, la variable statique a n'était pas initialisée.

13
naikus

Oui, tous les initialiseurs statiques sont exécutés avant que vous accédiez au cours pour la première fois. Si c'était autrement, j'appellerais ça un bug.

1
Nikita Rybak