web-dev-qa-db-fra.com

Enums - blocs statiques et d'instance

J'avais appris qu'en Java le bloc statique est exécuté lorsque la classe est initialisée et le bloc d'instance est exécuté avant la construction de chaque instance de la classe. J'avais toujours vu le bloc statique s'exécuter avant le bloc d'instance. Pourquoi la casse est-elle opposée pour enums?

Quelqu'un peut-il m'expliquer la sortie de l'exemple de code:

enum CoffeeSize {

    BIG(8), LARGE(10),HUGE(12),OVERWHELMING();
    private int ounces ;

    static {
        System.out.println("static block ");
    }
    {
        System.out.println("instance block");
    }

    private CoffeeSize(int ounces){
        this.ounces = ounces;
        System.out.println(ounces);
    }
    private CoffeeSize(){
        this.ounces = 20;
        System.out.println(ounces);
    }

    public int getOunces() {
        return ounces;
    }
} 

Production:

bloc d'instance
8
bloc d'instance
dix
bloc d'instance
12
bloc d'instance
20
bloc statique

34
NINCOMPOOP

Vous devez savoir que les valeurs d'énumération sont des champs statiques qui contiennent des instances de ce type d'énumération, et l'ordre d'initialisation des champs statiques dépend de leur position. Voir cet exemple

class SomeClass{
    public SomeClass() { System.out.println("creating SomeClass object"); }
}

class StaticTest{
    static{ System.out.println("static block 1"); }
    static SomeClass sc = new SomeClass();
    static{ System.out.println("static block 2"); }

    public static void main(String[] args) {
        new StaticTest();
    }
}

production

static block 1
creating SomeClass object
static block 2

Maintenant que les valeurs enum sont toujours placées au début du type enum, elles seront toujours appelées avant tout bloc d'initialisation statique, car tout le reste ne peut être déclaré qu'après les valeurs enum.
.

  • pour chaque valeur énumérée
  • et avant tout bloc d'initialisation statique.
34
Pshemo

Peu tard et s'appuyant sur réponse de Pshemo . La sortie du code (de compilation) ci-dessous est la suivante:

8
10
Foo
static block 
Bar

Ainsi, les initialisations des constantes enum sont exécutées en premier (comme l'a dit Pshemo, elles sont toujours implicitement static et final, voir le deuxième blockquote), puis tous les champs explicitement déclarés comme static sont initialisés . Comme mentionné, la spécification du langage le dit sur l'ordre d'exécution lors de l'initialisation de la classe et sur les constantes enum:

Ensuite, exécutez les initialiseurs de variable de classe et les initialiseurs statiques de la classe, ou les initialiseurs de champ de l'interface, dans l'ordre textuel , comme bien qu'ils n'étaient qu'un seul bloc.

En plus des membres qu'un type enum E hérite d'Enum, pour chaque constante enum déclarée avec le nom n, le type enum a un champ final public statique déclaré implicitement nommé n de type E . Ces champs sont considérés comme déclarés dans le même ordre que les constantes d'énumération correspondantes, avant tout champ statique déclaré explicitement dans le type d'énumération.


class StaticTest {
    enum CoffeeSize {
        BIG(8), LARGE(10);
        private int ounces;

        static Foo foo = new Foo();
        static { System.out.println("static block "); }
        static Bar bar = new Bar();

        private CoffeeSize(int ounces){
            this.ounces = ounces;
            System.out.println(ounces);
        }
    }
    public static void main(String[] args) {
        CoffeeSize cs = CoffeeSize.LARGE;
    }
}

class Foo { public Foo() { System.out.println("Foo"); } }
class Bar { public Bar() { System.out.println("Bar"); } }
9
Wolfram

Utilisez le bytecode pour résoudre ce problème.

import Java.util.ArrayList;
import Java.util.List;

public enum EnumDemo {
    ONE(1), TWO(2);

    private final static List<Integer> vals;
    static {
        System.out.println("fetch instance from static");
        vals = new ArrayList<>();
        EnumDemo[] values = EnumDemo.values();
        for (EnumDemo value : values) {
            vals.add(value.val);
        }
    }

    private int val;
    EnumDemo(int val){
        this.val = val;
        System.out.println("create instance:" + val);
    }

}

utilisez javac compile pour classer le fichier, puis javap -c EnumDemo.class, je l'ai:

Compiled from "EnumDemo.Java"
public final class EnumDemo extends Java.lang.Enum<EnumDemo> {
  public static final EnumDemo ONE;

  public static final EnumDemo TWO;

  public static EnumDemo[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[LEnumDemo;
       3: invokevirtual #2                  // Method "[LEnumDemo;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[LEnumDemo;"
       9: areturn       

  public static EnumDemo valueOf(Java.lang.String);
    Code:
       0: ldc_w         #4                  // class EnumDemo
       3: aload_0       
       4: invokestatic  #5                  // Method Java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       7: checkcast     #4                  // class EnumDemo
      10: areturn       

  static {};
    Code:
       0: new           #4                  // class EnumDemo
       3: dup           
       4: ldc           #16                 // String ONE
       6: iconst_0      
       7: iconst_1      
       8: invokespecial #17                 // Method "<init>":(Ljava/lang/String;II)V
      11: putstatic     #18                 // Field ONE:LEnumDemo;
      14: new           #4                  // class EnumDemo
      17: dup           
      18: ldc           #19                 // String TWO
      20: iconst_1      
      21: iconst_2      
      22: invokespecial #17                 // Method "<init>":(Ljava/lang/String;II)V
      25: putstatic     #20                 // Field TWO:LEnumDemo;
      28: iconst_2      
      29: anewarray     #4                  // class EnumDemo
      32: dup           
      33: iconst_0      
      34: getstatic     #18                 // Field ONE:LEnumDemo;
      37: aastore       
      38: dup           
      39: iconst_1      
      40: getstatic     #20                 // Field TWO:LEnumDemo;
      43: aastore       
      44: putstatic     #1                  // Field $VALUES:[LEnumDemo;
      47: getstatic     #8                  // Field Java/lang/System.out:Ljava/io/PrintStream;
      50: ldc           #21                 // String fetch instance from static
      52: invokevirtual #15                 // Method Java/io/PrintStream.println:(Ljava/lang/String;)V
      55: new           #22                 // class Java/util/ArrayList
      58: dup           
      59: invokespecial #23                 // Method Java/util/ArrayList."<init>":()V
      62: putstatic     #24                 // Field vals:Ljava/util/List;
      65: invokestatic  #25                 // Method values:()[LEnumDemo;
      68: astore_0      
      69: aload_0       
      70: astore_1      
      71: aload_1       
      72: arraylength   
      73: istore_2      
      74: iconst_0      
      75: istore_3      
      76: iload_3       
      77: iload_2       
      78: if_icmpge     109
      81: aload_1       
      82: iload_3       
      83: aaload        
      84: astore        4
      86: getstatic     #24                 // Field vals:Ljava/util/List;
      89: aload         4
      91: getfield      #7                  // Field val:I
      94: invokestatic  #26                 // Method Java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      97: invokeinterface #27,  2           // InterfaceMethod Java/util/List.add:(Ljava/lang/Object;)Z
     102: pop           
     103: iinc          3, 1
     106: goto          76
     109: return        
}

Ainsi, l'instance enum est l'instance statique et en tête.

1
Yanhui Zhou

1. Un type d'énumération est un type dont les champs sont constitués d'un ensemble fixe de constantes . Les exemples courants comprennent les directions de la boussole (valeurs de NORD, SUD, EST et OUEST) et les jours de la semaine.

2. Ce sont constante finale statique , ont donc toutes les lettres en majuscules .

3. Et les variables statiques sont initialisées dès que la JVM charge la classe.

Pour plus de détails, voir ce lien:

http://docs.Oracle.com/javase/1.5.0/docs/guide/language/enums.html

1
Kumar Vivek Mitra