Le code suivant imprime null
une fois.
class MyClass { private static MyClass myClass = new MyClass(); private static final Object obj = new Object(); public MyClass() { System.out.println(obj); } public static void main(Ssortingng[] args) {} }
Pourquoi les objects statiques ne sont-ils pas initialisés avant l’exécution du constructeur?
Mettre à jour
Je viens de copier cet exemple de programme sans attention, je pensais que nous parlions de 2 champs d’object, maintenant j’ai vu que le premier est un champ MyClass ..: /
Parce que les statiques sont initialisées dans l’ordre dans lequel elles sont données dans le code source.
Regarde ça:
class MyClass { private static MyClass myClass = new MyClass(); private static MyClass myClass2 = new MyClass(); public MyClass() { System.out.println(myClass); System.out.println(myClass2); } }
Cela va imprimer:
null null myClassObject null
MODIFIER
Ok, tirons ceci pour être un peu plus clair.
Est-ce clair?
EDIT 2
Comme Varman l’a fait remarquer, la référence à lui-même sera nulle lors de son initialisation. Ce qui a du sens si vous y réfléchissez.
Essayons une autre façon d’expliquer cela …
C’est la séquence traversée par la JVM lorsque vous faites référence pour la première fois à la classe MyClass
.
static { ... }
et static { ... }
blocs static { ... }
. myClass
initialise ensuite votre variable statique myClass
sur une nouvelle instance de MyClass
. MyClass
remarque que MyClass
est déjà chargé (code d’octet) et en cours d’initialisation , il ignore donc l’initialisation. obj
qui est toujours null
(car elle ne fait pas partie des variables initialisées par le tas et le constructeur). obj
sur une nouvelle instance de Object
. obj
ne serait pas null
mais une référence à une instance d’ Object
. Rappelez-vous que Java spécifie qu’une variable final
se voit atsortingbuer une valeur une fois. Il n’est pas garanti qu’une valeur lui soit assignée lorsque le code le référence, sauf si vous vous assurez que le code le référence après son affectation.
Ce n’est pas un bug. C’est le moyen défini pour gérer l’utilisation de la classe lors de sa propre initialisation. Si ce n’était pas le cas, la JVM entrerait dans une boucle infinie. Voir l’étape 3.3 (si la JVM ne saute pas l’initialisation pour une classe en cours d’initialisation, elle se contente de l’initialiser – boucle infinie).
Notez également que tout se passe sur le même thread qui référence la classe en premier. Deuxièmement, la machine virtuelle Java garantit que l’initialisation se terminera avant qu’un autre thread puisse utiliser cette classe.
C’est parce que Java exécute la section statique dans l’ordre où il est déclaré. Dans votre cas, la séquence est
Lorsque # 1 est exécuté, obj n’est toujours pas initialisé et affiche donc null. Essayez ce qui suit et vous verrez la différence:
class MyClass { private static final Object obj = new Object(); private static MyClass myClass = new MyClass(); public MyClass() { System.out.println(obj); // will print null once } }
De manière générale, il vaut mieux éviter une telle construction tous ensemble. Si vous essayez de créer un singleton, voici comment ce fragment de code devrait ressembler à:
class MyClass { private static final MyClass myClass = new MyClass(); private Object obj = new Object(); private MyClass() { System.out.println(obj); // will print null once } }
c’est-à-dire que les champs statiques initialisés dans le même ordre qu’ils ont défini.
@Pyrolistique
puisque l’initiale du premier champ statique myclass n’est pas entièrement construite … le résultat est
null null testInitialize.MyObject@70f9f9d8 null