È 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 Enumstesso.
Come puoi vedere, l'inizializzatore statico accede anche al privatecampo aliases. È importante capire che il staticblocco ha già accesso alle Enumistanze del valore (ad es ENGLISH.). Questo perché l' ordine di inizializzazione ed esecuzione nel caso dei Enumtipi , proprio come se i static privatecampi fossero stati inizializzati con istanze prima che i staticblocchi fossero stati chiamati:
- Le
Enumcostanti 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 staticblocco) è 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)