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 Enummismo.
Como puede ver, el inicializador estático accede incluso al privatecampo aliases. Es importante comprender que el staticbloque ya tiene acceso a las Enuminstancias de valor (p ENGLISH. Ej .). Esto se debe al orden de inicialización y ejecución en el caso de los Enumtipos , como si los static privatecampos se hubieran inicializado con instancias antes de staticque se llamaran los bloques:
- Las
Enumconstantes 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 staticimportante 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)