Disons qu’un projet contient plusieurs classes, chacune ayant un bloc d’initialisation statique. Dans quel ordre ces blocs fonctionnent-ils? Je sais que dans une classe, ces blocs sont exécutés dans l’ordre dans lequel ils apparaissent dans le code. J’ai lu que c’est la même chose dans toutes les classes, mais un exemple de code que j’ai écrit est en désaccord avec cela. J’ai utilisé ce code:
package pkg; public class LoadTest { public static void main(Ssortingng[] args) { System.out.println("START"); new Child(); System.out.println("END"); } } class Parent extends Grandparent { // Instance init block { System.out.println("instance - parent"); } // Constructor public Parent() { System.out.println("constructor - parent"); } // Static init block static { System.out.println("static - parent"); } } class Grandparent { // Static init block static { System.out.println("static - grandparent"); } // Instance init block { System.out.println("instance - grandparent"); } // Constructor public Grandparent() { System.out.println("constructor - grandparent"); } } class Child extends Parent { // Constructor public Child() { System.out.println("constructor - child"); } // Static init block static { System.out.println("static - child"); } // Instance init block { System.out.println("instance - child"); } }
et a obtenu cette sortie:
DÉBUT
statique – grand-parent
statique – parent
statique – enfant
exemple – grand-parent
constructeur – grand-père
instance – parent
constructeur – parent
instance – enfant
constructeur – enfant
FIN
La réponse évidente à cette question est que les blocs des parents s’exécutent avant leurs enfants, mais cela pourrait être une simple coïncidence et cela n’aide pas si deux classes ne sont pas dans la même hiérarchie.
MODIFIER:
J’ai modifié mon code exemple en ajoutant ceci à LoadTest.java:
class IAmAClassThatIsNeverUsed { // Constructor public IAmAClassThatIsNeverUsed() { System.out.println("constructor - IAACTINU"); } // Instance init block { System.out.println("instance - IAACTINU"); } // Static init block static { System.out.println("static - IAACTINU"); } }
Comme l’indique le nom de la classe, je n’ai jamais référencé la nouvelle classe. Le nouveau programme a produit le même résultat que l’ancien.
L’initialiseur statique d’une classe est exécuté lors du premier access à la classe, soit pour créer une instance, soit pour accéder à une méthode ou un champ statique.
Donc, pour plusieurs classes, cela dépend totalement du code exécuté pour que ces classes soient chargées.
Reportez-vous aux sections 12.4 et 12.5 de la version 8 de JLS , qui détaillent tout cela (12.4 pour les variables static et 12.5 pour les variables d’instance).
Pour l’initialisation statique (section 12.4):
Une classe ou un type d’interface T sera initialisé immédiatement avant la première occurrence de l’un des éléments suivants:
(et plusieurs clauses de Weasel-Word)
Les réponses de Keith et de Chris sont toutes deux excellentes, j’ajoute juste un peu plus de détails pour ma question spécifique.
Les blocs d’initialisation statiques s’exécutent dans l’ordre d’initialisation de leurs classes. Alors, quel est cet ordre? Par JLS 12.4.1:
Une classe ou un type d’interface T sera initialisé immédiatement avant la première occurrence de l’un des éléments suivants:
- T est une classe et une instance de T est créée.
- T est une classe et une méthode statique déclarée par T est invoquée.
- Un champ statique déclaré par T est affecté.
- Un champ statique déclaré par T est utilisé et le champ n’est pas une variable constante (§4.12.4).
- T est une classe de premier niveau et une instruction assert (§14.10) nestede lexicalement dans T est exécutée.
L’invocation de certaines méthodes de reflection dans la classe Class et dans le package java.lang.reflect provoque également l’initialisation de la classe ou de l’interface. Une classe ou une interface ne sera pas initialisée sous aucune autre circonstance.
Pour illustrer cela, voici un aperçu de ce qui se passe dans l’exemple:
L’initialisation d’une classe consiste à exécuter ses initialiseurs statiques et les initialiseurs pour les champs statiques (variables de classe) déclarés dans la classe.
L’initialisation d’une interface consiste à exécuter les initialiseurs pour les champs (constantes) déclarés dans l’interface.
Avant qu’une classe soit initialisée, sa super-classe directe doit être initialisée, mais les interfaces implémentées par la classe ne sont pas initialisées. De même, les super-interfaces d’une interface ne sont pas initialisées avant que l’interface ne soit initialisée.
Vous pouvez avoir plusieurs initialiseurs statiques et d’instance dans la même classe, donc
Chacun est exécuté comme s’il s’agissait d’un bloc unique.
http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
veuillez vérifier la documentation de Java.
alors clairement mentionné, peu importe la façon dont les blocs statiques sont là, ils seront exécutés dans un seul bloc dans l’ordre où ils apparaissent
Alors,
Ma compréhension ici est que java regarde votre code comme
static{ i=1; i=2; }
static int i;
c’est pourquoi vous obtenez la sortie 2
j’espère que c’est utile
Il y a un cas dans lequel un bloc statique ne sera pas appelé.
class Super { public static int i=10; } class Sub extends Super { static { system.out.println("Static block called"); } } class Test { public static void main (Ssortingng [] args) { system.out.println(Sub.i); } }
Les sorties de code ci-dessus 10