68 votes

Pourquoi .class n'invoque-t-il pas le bloc statique dans une classe ?

Voici le code que j'ai :

public class StupidClass {
    static {
        System.out.println("Stupid class loaded!");
    }
}

Et les tests que j'ai, que j'exécute séparément .

import org.junit.Test;

public class StupidTest {
    @Test
    public void foo() throws ClassNotFoundException {
        final Class<?> stupidClass = Class.forName("StupidClass");
        System.out.println(stupidClass.getSimpleName());
    }

    @Test
    public void bar() throws ClassNotFoundException {
        final Class<StupidClass> stupidClassClass = StupidClass.class;
        System.out.println(stupidClassClass.getSimpleName());
    }
}

Lorsque je lance le test foo Je vais voir :

Stupid class loaded!
StupidClass

Mais quand je lance le test bar tout ce que je vois c'est :

StupidClass

Citation de este page..

Les objets de classe sont construits automatiquement par la machine virtuelle Java machine virtuelle Java lors du chargement des classes et par des appels à la méthode defineClass dans le chargeur de classes.

Si je comprends bien, dans la barre de test, la classe Stupid est chargée, sinon j'aurais vu un null je suppose ? Donc l'objet Class est créé parce que la classe elle-même est chargée

Et maintenant, je cite este page

Les blocs d'initialisation statiques sont exécutés lorsque la JVM (le chargeur de classe - pour chargeur de classes) charge la StaticClass (ce qui se produit la première fois qu'elle est référencée dans le code).

Je m'attends donc à voir le texte "Stupid class loaded !" dans la barre de test également, mais ce n'est pas le cas.

Citant également Penser en Java

Chacune des classes Candy, Gum, et Cookie possède une clause statique qui est exécutée lorsque la classe est chargée pour la première fois.

ce qui n'est pas très précis, semble-t-il

Qu'est-ce que je rate ?

60voto

Marko Topolnik Points 77257

Les blocs d'initialisation statiques sont exécutés lorsque la JVM (le chargeur de classe - pour être précis) charge la StaticClass (ce qui se produit la première fois qu'elle est référencée dans le code).

La citation ci-dessus est tout simplement fausse, mais elle n'est qu'un exemple d'une idée fausse très répandue.

  1. Classe n'est pas initialisé lorsqu'elle est chargée, mais lorsqu'une classe statique membre est référencé en premier. Ceci est précisément régi par le spécification .

  2. Chargement des classes ne se produit pas lorsque la classe est référencée pour la première fois, mais à un moment qui dépend de l'implémentation.

  3. Le dernier moment où la classe doit être chargée est celui où la classe est référencée, ce qui est pas la même chose comme référence à une classe membre .

Class.forName initialise la classe par défaut, mais vous avez le choix d'appeler une surcharge qui prend une valeur de boolean initialize et de fournir false . Vous obtiendrez la classe chargée sans initialisation.

23voto

TheLostMind Points 10813

Le chargement des classes et l'initialisation sont deux choses différentes. Une classe peut être chargée mais pas initialisée avant que cela ne soit vraiment nécessaire. Les initialisateurs statiques ne sont exécutés que lorsqu'une classe est initialisée <> PAS chargée, "initialisée".

Dans le premier cas, vous chargez et initialisez une classe lorsque vous utilisez la fonction class.forName() c'est pourquoi les initialisateurs statiques sont exécutés et c'est pourquoi vous voyez "Stupid class loaded!" comme sortie . Dans le second cas, vous ne faites qu'assigner une référence de la classe, la classe est chargée (utilisez java -verbose:class pour voir quelles classes sont chargées) mais vous ne l'initialisez pas vraiment (ou pour être plus précis, vous ne faites rien qui force l'exécution des initialisateurs). Ainsi, vous ne voyez pas la sortie comme Stupid class loaded! . Essayez de faire quelque chose comme appeler newInstance() sur la classe, cela devrait forcer l'initialisation de la classe et vous devriez voir Stupid class loaded!

Mon code :

public class CheckPalindrome {

    public static void main(String[] args) {
        Class<Test> t = Test.class;
    }

}
// class being loaded
class Test {
    static {
        System.out.println("aaa");
    }
}

Les classes qui sont chargées

...
[Loaded Test from file:/Workspaces/SampleTest/Java8/bin/]
...

^ - Cela montre que la classe est chargée mais pas initialisée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X