Es un error común pensar que un bloque estático solo tiene acceso a campos estáticos. Para esto, me gustaría mostrar a continuación el código que utilizo con bastante frecuencia en proyectos de la vida real (copiado parcialmente de otra respuesta en un contexto ligeramente diferente):
public enum Language {
ENGLISH("eng", "en", "en_GB", "en_US"),
GERMAN("de", "ge"),
CROATIAN("hr", "cro"),
RUSSIAN("ru"),
BELGIAN("be",";-)");
static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>();
static {
for (Language l:Language.values()) {
// ignoring the case by normalizing to uppercase
ALIAS_MAP.put(l.name().toUpperCase(),l);
for (String alias:l.aliases) ALIAS_MAP.put(alias.toUpperCase(),l);
}
}
static public boolean has(String value) {
// ignoring the case by normalizing to uppercase
return ALIAS_MAP.containsKey(value.toUpper());
}
static public Language fromString(String value) {
if (value == null) throw new NullPointerException("alias null");
Language l = ALIAS_MAP.get(value);
if (l == null) throw new IllegalArgumentException("Not an alias: "+value);
return l;
}
private List<String> aliases;
private Language(String... aliases) {
this.aliases = Arrays.asList(aliases);
}
}
Aquí el inicializador se utiliza para mantener un índice ( ALIAS_MAP
), para asignar un conjunto de alias al tipo de enumeración original. Está destinado a ser una extensión del método valueOf incorporado proporcionado por el Enum
mismo.
Como puede ver, el inicializador estático accede incluso al private
campo aliases
. Es importante comprender que el static
bloque ya tiene acceso a las Enum
instancias de valor (p ENGLISH
. Ej .). Esto se debe al orden de inicialización y ejecución en el caso de los Enum
tipos , como si los static private
campos se hubieran inicializado con instancias antes de static
que se llamaran los bloques:
- Las
Enum
constantes que son campos estáticos implícitos. Esto requiere que el constructor Enum y los bloques de instancia, y la inicialización de la instancia también ocurran primero.
static
bloque e inicialización de campos estáticos en el orden de ocurrencia.
Es static
importante tener en cuenta esta inicialización fuera de orden (constructor antes del bloque). También sucede cuando inicializamos campos estáticos con las instancias de manera similar a un Singleton (simplificaciones hechas):
public class Foo {
static { System.out.println("Static Block 1"); }
public static final Foo FOO = new Foo();
static { System.out.println("Static Block 2"); }
public Foo() { System.out.println("Constructor"); }
static public void main(String p[]) {
System.out.println("In Main");
new Foo();
}
}
Lo que vemos es el siguiente resultado:
Static Block 1
Constructor
Static Block 2
In Main
Constructor
Claro es que la inicialización estática en realidad puede ocurrir antes del constructor, e incluso después:
Simplemente acceder a Foo en el método principal hace que se cargue la clase y se inicie la inicialización estática. Pero como parte de la inicialización estática, nuevamente llamamos a los constructores para los campos estáticos, después de lo cual reanuda la inicialización estática y completa el constructor llamado desde el método principal. Situación bastante compleja para la que espero que en la codificación normal no tengamos que lidiar.
Para obtener más información sobre esto, consulte el libro " Java eficaz ".
{...}
vsstatic {...}
. (en cuyo caso Jon Skeet definitivamente respondió su pregunta mucho mejor)