93 votes

Statique bloc en Java n'est pas exécuté

class Test{
    public static void main(String arg[]){    
        System.out.println("**MAIN METHOD");
        System.out.println(Mno.VAL);//SOP(9090);
        System.out.println(Mno.VAL+100);//SOP(9190);
    }

}

class Mno{
    final static int VAL=9090;
    static{
        System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
    }
}

Je sais qu'un static bloc exécuté lors de la classe chargée. Mais dans ce cas, la variable d'instance à l'intérieur de la classe Mno est final, en raison de l' static bloc n'est pas en cours d'exécution.

Pourquoi donc? Et si je voulais supprimer l' final, serait-il fonctionner?

De mémoire qui sera affectée en premier lieu, l' static final variable ou de l' static bloc?

Si, en raison de l' final modificateur d'accès à la classe de ne pas se charger, puis comment la variable d'obtenir la mémoire?

141voto

Marko Topolnik Points 77257
  1. Un static final int champ est une constante de compilation , et sa valeur est codé en dur dans la classe de destination, sans référence à son origine;
  2. par conséquent, votre classe principale ne déclenche pas le chargement de la classe contenant le terrain;
  3. par conséquent, l'initialiseur statique de la classe n'est pas exécutée.

Dans le détail, le code compilé correspond à ceci:

public static void main(String arg[]){    
    System.out.println("**MAIN METHOD");
    System.out.println(9090)
    System.out.println(9190)
}

Dès que vous retirez final, il n'est plus une constante de compilation et le comportement décrit ci-dessus ne s'applique pas. L' Mno classe est chargé que vous attendez et ses initialiseur statique s'exécute.

8voto

assylias Points 102015

La raison pour laquelle la classe n'est pas chargé, c'est que VAL est final ET il est initialisé avec une expression constante (9090). Si, et seulement si ces deux conditions sont remplies, la constante est évaluée au moment de la compilation et de "codé en dur" en cas de besoin.

Pour empêcher l'expression de l'être évalué au moment de la compilation (et de faire de la JVM charge de votre classe), vous pouvez soit:

  • supprimer le mot-clé final:

    static int VAL = 9090; //not a constant variable any more
    
  • ou de changer le côté droit de l'expression de quelque chose de non constante (même si la variable est encore définitif):

    final static int VAL = getInt(); //not a constant expression any more
    static int getInt() { return 9090; }
    

5voto

Xolve Points 4422

Si vous voyez le bytecode généré à l'aide de javap -v Test.class, main() sort comme:

public static void main(java.lang.String[]) throws java.lang.Exception;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String **MAIN METHOD
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        11: sipush        9090
        14: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        17: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        20: sipush        9190
        23: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        26: return        

Vous pouvez clairement voir dans "11: sipush 9090" que statique de la valeur finale est directement utilisé, parce que Mno.VAL est une compilation constante de temps. Par conséquent, il n'est pas nécessaire de charger La classe. Donc statique bloc de Mno n'est pas exécutée.

Vous pouvez exécuter le bloc statique manuelle de chargement Mno comme ci-dessous:

class Test{
    public static void main(String arg[]) throws Exception {
        System.out.println("**MAIN METHOD");
        Class.forName("Mno");                 // Load Mno
        System.out.println(Mno.VAL);
        System.out.println(Mno.VAL+100);
    }

}

class Mno{
    final static int VAL=9090;
    static{
        System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
    }
}

1voto

Ketan_Patel Points 11

1)en Fait vous ne l'avez pas fait en sorte que la Mno de la classe lors de la compilation de commencer, il va générer de la constante de la variable VAL et lors de l'exécution de commencer quand cette variable est nécessaire que sa charge, c'est à partir de la mémoire.donc ce n'est pas nécessaire de votre classe de référence, de sorte que statique bock n'est pas exécutée.

2)si Une classe de prolonger de Mno classe au moment de la statique bloc est inclus dans Une classe si vous faites cela, alors que statique bloc est exécuté. par exemple.. public class A extends Mno{

public static void main(String arg[]){    
    System.out.println("**MAIN METHOD");
    System.out.println(Mno.VAL);//SOP(9090);
    System.out.println(Mno.VAL+100);//SOP(9190);
}

}

class Mno{
      final static int VAL=9090;
    static`{`
        System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
    }
}

0voto

Fabyen Points 52

Autant que je sache, il sera exécuté dans l'ordre d'apparition. Par exemple :

 public class Statique {
     public static final String value1 = init1();

     static {
         System.out.println("trace middle");
     }
     public static final String value2 = init2();


     public static String init1() {
         System.out.println("trace init1");
         return "1";
     }
     public static String init2() {
         System.out.println("trace init2");
         return "2";
     }
 }

imprime

  trace init1
  trace middle
  trace init2

Je viens de testé et de la statique sont initialisés (=> imprimer) lorsque la classe "Statique" est effectivement utilisé et "exécuté" dans un autre morceau de code (mon cas je n'ai "nouvelle Statique()".

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