È un'idea sbagliata comune pensare che un blocco statico abbia accesso solo ai campi statici. Per questo vorrei mostrare sotto un pezzo di codice che uso abbastanza spesso in progetti di vita reale (copiato parzialmente da un'altra risposta in un contesto leggermente diverso):
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);
}
}
Qui l'inizializzatore viene utilizzato per mantenere un indice ( ALIAS_MAP
), per mappare un set di alias al tipo di enum originale. È inteso come estensione del metodo valueOf incorporato fornito dallo Enum
stesso.
Come puoi vedere, l'inizializzatore statico accede anche al private
campo aliases
. È importante capire che il static
blocco ha già accesso alle Enum
istanze del valore (ad es ENGLISH
.). Questo perché l' ordine di inizializzazione ed esecuzione nel caso dei Enum
tipi , proprio come se i static private
campi fossero stati inizializzati con istanze prima che i static
blocchi fossero stati chiamati:
- Le
Enum
costanti che sono campi statici impliciti. Ciò richiede il costruttore Enum e i blocchi di istanza e anche l'inizializzazione dell'istanza deve avvenire per prima.
static
blocco e inizializzazione di campi statici nell'ordine in cui si verificano.
Questa inizializzazione fuori ordine (costruttore prima del static
blocco) è importante da notare. Succede anche quando inizializziamo i campi statici con le istanze in modo simile a un Singleton (semplificazioni apportate):
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();
}
}
Quello che vediamo è il seguente output:
Static Block 1
Constructor
Static Block 2
In Main
Constructor
È chiaro che l'inizializzazione statica può effettivamente avvenire prima del costruttore e anche dopo:
Il semplice accesso a Foo nel metodo principale provoca il caricamento della classe e l'avvio dell'inizializzazione statica. Ma come parte dell'inizializzazione statica chiamiamo nuovamente i costruttori per i campi statici, dopo di che riprende l'inizializzazione statica e completa il costruttore chiamato dall'interno del metodo principale. Situazione piuttosto complessa per la quale spero che nella normale codifica non dovremmo affrontare.
Per maggiori informazioni a riguardo vedi il libro " Efficace Java ".
{...}
vsstatic {...}
. (nel qual caso Jon Skeet ha sicuramente risposto alla tua domanda molto meglio)