java - example - Enums-bloques estáticos y de instancia
java enum valueof (4)
Aprendí que en Java, el bloque estático se ejecuta cuando la clase se inicializa y el bloque de instancia se ejecuta antes de la construcción de cada instancia de la clase. Siempre había visto el bloque estático para ejecutar antes del bloque de instancia. ¿Por qué el caso es opuesto para las enums
?
¿Puede alguien explicarme la salida del código de muestra?
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;
}
}
Salida:
bloque de instancia
8
bloque de instancia
10
bloque de instancia
12
bloque de instancia
20
bloque estático
Debe saber que los valores de enumeración son campos estáticos que contienen instancias de ese tipo de enumeración, y el orden de inicialización de los campos estáticos depende de su posición. Ver este ejemplo
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();
}
}
salida
static block 1
creating SomeClass object
static block 2
Ahora, dado que los valores de enumeración siempre se colocan al inicio del tipo de enumeración, siempre se llamarán antes de cualquier bloque de inicialización estática, porque todo lo demás solo se puede declarar después de los valores de enumeración.
PERO la inicialización de los valores de enumeración (que ocurre en la inicialización de la clase) se llama a sus constructores y, como usted dijo, los bloques de inicialización no estáticos se ejecutan al inicio de cada constructor, por eso los ve:
- por cada valor de enumeración
- y antes de cualquier bloque de inicialización estática.
Poco tarde y construyendo sobre la respuesta de Pshemo . La salida del código (compilación) a continuación es la siguiente:
8
10
Foo
static block
Bar
Por lo tanto, las inicializaciones constantes de la enumeración se ejecutan primero (como dijo Pshemo, siempre son implícitamente static
y final
, consulte la segunda cita del bloque) y luego todos los campos declarados explícitamente como static
se inicializan. Como se mencionó, la especificación del lenguaje dice esto sobre el orden de ejecución durante la inicialización de la clase y sobre las constantes de enumeración:
Además de los miembros que un tipo de enumeración E hereda de Enum, para cada constante de enumeración declarada con el nombre n, el tipo de enumeración tiene un campo final estático público declarado implícitamente llamado n de tipo E. Estos campos se consideran declarados en el mismo orden que las constantes de enumeración correspondientes, antes de los campos estáticos declarados explícitamente en el tipo de enumeración.
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"); } }
Utilice el código de bytes para resolver este problema.
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);
}
}
use javac compile to class file, y luego javap -c EnumDemo.class
, obtuve esto:
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
}
Por lo tanto, la instancia de enumeración es la instancia estática, y en la cabeza.
1. Un tipo de enumeración es un tipo cuyos campos consisten en un conjunto fijo de constantes . Los ejemplos comunes incluyen direcciones de la brújula (valores del NORTE, SUR, ESTE y OESTE) y los días de la semana.
2. Son constantes finales estáticas , por lo tanto tienen todas las letras en mayúsculas.
3. Y las variables estáticas se inicializan tan pronto como la JVM carga la clase.
Para más detalles ver este enlace:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html