Es ist ein weit verbreitetes Missverständnis zu glauben, dass ein statischer Block nur Zugriff auf statische Felder hat. Dazu möchte ich im Folgenden einen Teil des Codes zeigen, den ich häufig in realen Projekten verwende (teilweise aus einer anderen Antwort in einem etwas anderen Kontext kopiert ):
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);
}
}
Hier wird der Initialisierer verwendet, um einen Index ( ALIAS_MAP
) zu verwalten und eine Reihe von Aliasen wieder dem ursprünglichen Aufzählungstyp zuzuordnen. Es ist als Erweiterung der integrierten valueOf-Methode gedacht, die von sich Enum
selbst bereitgestellt wird .
Wie Sie sehen können, greift der statische Initialisierer sogar auf das private
Feld zu aliases
. Es ist wichtig zu verstehen, dass der static
Block bereits Zugriff auf die Enum
Wertinstanzen hat (z ENGLISH
. B. ). Dies liegt daran, dass die Reihenfolge der Initialisierung und Ausführung bei Enum
Typen so ist , als ob die static private
Felder mit Instanzen initialisiert wurden, bevor die static
Blöcke aufgerufen wurden:
- Die
Enum
Konstanten, die implizite statische Felder sind. Dies erfordert den Enum-Konstruktor und die Instanzblöcke, und die Instanzinitialisierung muss ebenfalls zuerst erfolgen.
static
Blockierung und Initialisierung statischer Felder in der Reihenfolge ihres Auftretens.
Diese Initialisierung außerhalb der Reihenfolge (Konstruktor vor static
Block) ist wichtig zu beachten. Es passiert auch, wenn wir statische Felder mit den Instanzen ähnlich einem Singleton initialisieren (Vereinfachungen vorgenommen):
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();
}
}
Was wir sehen, ist die folgende Ausgabe:
Static Block 1
Constructor
Static Block 2
In Main
Constructor
Klar ist, dass die statische Initialisierung tatsächlich vor dem Konstruktor und sogar danach erfolgen kann:
Durch einfachen Zugriff auf Foo in der Hauptmethode wird die Klasse geladen und die statische Initialisierung gestartet. Im Rahmen der statischen Initialisierung rufen wir jedoch erneut die Konstruktoren für die statischen Felder auf. Danach wird die statische Initialisierung fortgesetzt und der aus der Hauptmethode aufgerufene Konstruktor vervollständigt. Ziemlich komplexe Situation, für die ich hoffe, dass wir uns bei normaler Codierung nicht damit befassen müssen.
Weitere Informationen hierzu finden Sie im Buch " Effective Java ".
{...}
vsstatic {...}
. (In diesem Fall hat Jon Skeet Ihre Frage definitiv besser beantwortet)