Поширена помилка думати, що статичний блок має доступ лише до статичних полів. Для цього я хотів би показати нижче фрагмент коду, який я досить часто використовую в реальних проектах (частково скопійований з іншої відповіді в дещо іншому контексті):
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 {...}
. (в такому випадку Джон Скіт однозначно відповів на ваше питання набагато краще)