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
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.
.
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:
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"); } }
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. 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