Il est faux de penser qu'un bloc statique n'a accès qu'aux champs statiques. Pour cela, je voudrais montrer ci-dessous un morceau de code que j'utilise assez souvent dans des projets réels (copié partiellement à partir d' une autre réponse dans un contexte légèrement différent):
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);
}
}
Ici, l'initialiseur est utilisé pour maintenir un index ( ALIAS_MAP
), pour mapper un ensemble d'alias au type d'énumération d'origine. Il est conçu comme une extension de la méthode intégrée valueOf fournie par leEnum
lui même.
Comme vous pouvez le voir, l'initialiseur statique accède même au private
champ aliases
. Il est important de comprendre que le static
bloc a déjà accès aux Enum
instances de valeur (par exemple ENGLISH
). En effet, l' ordre d'initialisation et d'exécution dans le cas des Enum
types , comme si les static private
champs avaient été initialisés avec des instances avant l' static
appel des blocs:
- Les
Enum
constantes qui sont des champs statiques implicites. Cela nécessite le constructeur Enum et les blocs d'instance, et l'initialisation d'instance doit également se produire en premier.
static
bloc et initialisation des champs statiques dans l'ordre d'apparition.
Cette initialisation désordonnée (constructeur avant static
bloc) est importante à noter. Cela se produit également lorsque nous initialisons des champs statiques avec les instances de manière similaire à un singleton (simplifications apportées):
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();
}
}
Ce que nous voyons est la sortie suivante:
Static Block 1
Constructor
Static Block 2
In Main
Constructor
Il est clair que l'initialisation statique peut réellement se produire avant le constructeur, et même après:
Le simple accès à Foo dans la méthode principale provoque le chargement de la classe et le démarrage de l'initialisation statique. Mais dans le cadre de l'initialisation statique, nous appelons à nouveau les constructeurs des champs statiques, après quoi il reprend l'initialisation statique et termine le constructeur appelé depuis la méthode principale. Situation assez complexe pour laquelle j'espère qu'en codage normal nous n'aurions pas à faire face.
Pour plus d'informations à ce sujet, consultez le livre " Java efficace ".
{...}
vsstatic {...}
. (auquel cas Jon Skeet a définitivement mieux répondu à votre question)