Поширена помилка думати, що статичний блок має доступ лише до статичних полів. Для цього я хотів би показати нижче фрагмент коду, який я досить часто використовую в реальних проектах (частково скопійований з іншої відповіді в дещо іншому контексті):
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);
}
}
Тут ініціалізатор використовується для підтримки індексу ( ALIAS_MAP), для набору набору псевдонімів до початкового типу enum. Він призначений як розширення до вбудованого методу valueOf, наданого самим Enumсобою.
Як бачите, статичний ініціалізатор отримує доступ навіть до privateполя aliases. Важливо розуміти, що staticблок вже має доступ до Enumекземплярів значень (наприклад ENGLISH). Це тому, що порядок ініціалізації та виконання у випадку Enumтипів , так само, як якщо б static privateполя були ініціалізовані з екземплярами до staticвиклику блоків:
- Ці
Enumконстанти , які є неявними полями статичних. Для цього потрібні блоки конструктора та екземпляра Enum та ініціалізація екземплярів.
static блокування та ініціалізація статичних полів у порядку виникнення.
staticВажливо відзначити цю ініціалізацію поза замовленням (конструктор перед блоком). Це трапляється і тоді, коли ми ініціалізуємо статичні поля з екземплярами аналогічно Singleton (зроблено спрощення):
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();
}
}
Ми бачимо такий результат:
Static Block 1
Constructor
Static Block 2
In Main
Constructor
Зрозуміло, що статична ініціалізація насправді може статися перед конструктором і навіть після:
Простий доступ до Foo в основному методі призводить до завантаження класу та запуску статичної ініціалізації. Але в рамках статичної ініціалізації ми знову викликаємо конструктори для статичних полів, після чого він поновлює статичну ініціалізацію, і завершує конструктор, викликаний зсередини основного методу. Досить складна ситуація, для якої я сподіваюся, що при нормальному кодуванні нам не доведеться мати справу.
Більш детальну інформацію про це дивіться у книзі " Ефективна Java ".
{...}протиstatic {...}. (в такому випадку Джон Скіт однозначно відповів на ваше питання набагато краще)