Supposons qu'un projet contient plusieurs classes, chacune d'entre elles ayant un bloc d'initialisation statique. Dans quel ordre ces blocs fonctionnent-ils? Je sais qu'au sein d'une classe, de tels blocs sont exécutés dans l'ordre dans lequel ils apparaissent dans le code. J'ai lu que c'était la même chose d'une classe à l'autre, mais un exemple de code que j'ai écrit n'est pas d'accord avec cela. J'ai utilisé ce code:
package pkg;
public class LoadTest {
public static void main(String[] 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 obtenu cette sortie:
DÉBUT
statique - grand-parent
statique - parent
statique - enfant
exemple - grand-parent
constructeur - grand-parent
instance - parent
constructeur - parent
instance - enfant
constructeur - enfant
FIN
La réponse évidente à cela est que les blocs des parents fonctionnent avant ceux de leurs enfants, mais cela pourrait simplement être une coïncidence et n'aiderait pas si deux classes n'étaient pas dans la même hiérarchie.
MODIFIER:
J'ai modifié mon exemple de code en l'ajoutant à 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 nulle part. 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 accès à la classe, que ce soit pour créer une instance ou pour accéder à une méthode ou à un champ statique.
Donc, pour plusieurs classes, cela dépend totalement du code qui est exécuté pour que ces classes soient chargées.
Reportez-vous aux sections 12.4 et 12.5 du JLS version 8 , pour en savoir plus sur tout cela (12.4 pour les variables statiques et 12.5 pour les variables d'instance).
Pour l’initialisation statique (section 12.4):
Une classe ou une interface de type T sera initialisée immédiatement avant la première occurrence de l’un des opérations suivantes:
(et plusieurs clauses Weasel-Word)
Les réponses de Keith et de Chris sont excellentes. J'ajoute juste quelques détails supplémentaires pour ma question spécifique.
Les blocs d'initialisation statiques s'exécutent dans l'ordre d'initialisation de leurs classes. Alors, quel ordre est-ce? Selon JLS 12.4.1:
Une classe ou une interface de type T sera initialisée immédiatement avant la première occurrence de l’un des opérations suivantes:
- 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 appelé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 niveau supérieur et une instruction assert (§14.10) imbriquée lexicalement dans T est exécutée.
L'invocation de certaines méthodes de réflexion dans la classe Class et dans le package Java.lang.reflect entraîne également l'initialisation de la classe ou de l'interface. Une classe ou une interface ne sera initialisée dans 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 des champs statiques (variables de classe) déclarés dans la classe.
L'initialisation d'une interface consiste à exécuter les initialiseurs des champs (constantes) déclarés dans l'interface.
Avant qu'une classe ne 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 l'initialisation de l'interface.
http://docs.Oracle.com/javase/tutorial/Java/javaOO/initial.html
veuillez vérifier la documentation Java.
puis clairement mentionné, peu importe la façon dont les blocs statiques sont présents, ils seront exécutés comme un seul bloc dans l'ordre dans lequel ils apparaissent
Alors,
Si je comprends bien, Java cherche votre code comme
static{
i=1;
i=2;
}
statique int i;
c'est pourquoi vous obtenez la sortie 2
espérons que cela vous sera utile
Il existe 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 (String [] args) {
system.out.println(Sub.i);
}
}
Le code ci-dessus renvoie 10
class A {
public A() {
// 2
}
}
class B extends A{
static char x = 'x'; // 0
char y = 'y'; // 3
public B() {
// 4
}
public static void main(String[] args) {
new B(); // 1
}
}
Les chiffres dans le commentaire indiquent l'ordre d'évaluation, le plus petit, le plus tôt.
Comme le montre l'exemple,
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 seul bloc.