Это распространенное заблуждение думать, что статический блок имеет доступ только к статическим полям. Для этого я хотел бы показать ниже кусок кода, который я довольно часто использую в реальных проектах (скопированный частично из another answer в несколько ином контексте):
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
), чтобы сопоставить набор псевдонимов с исходным типом перечисления. Он предназначен как расширение встроенного метода valueOf, предоставленного самим Enum
.
Как вы можете видеть, статический инициализатор обращается даже к полю private
aliases
. Важно понимать, что блок static
уже имеет доступ к экземплярам значения Enum
(например, ENGLISH
). Это происходит потому, что order of initialization and execution in the case of Enum
types, так же, как если 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 в основном методе, заставляет класс загружаться и статическая инициализация запускается. Но в рамках статической инициализации мы снова вызываем конструкторы для статических полей, после чего она возобновляет статическую инициализацию и завершает конструктор, вызванный из основного метода. Скорее сложная ситуация, на которую я надеюсь, что при нормальном кодировании нам не придется иметь дело.
Для получения дополнительной информации об этом см. Книгу «Effective Java».
Minor обратной связи, но это помогло бы, если бы Вы, пожалуйста, укажите ваши предположения ясно, и, следовательно, уточнить, какой ответ является правильным. когда я впервые прочитал ваш вопрос, я понял неправильно и подумал, что вы знаете разницу между '{...}' vs 'static {...}'. (в этом случае Джон Скит определенно ответил на ваш вопрос лучше) –
Этот вопрос очень неясен; у вас есть ответчики, которые скремблируют и делают много укоренившихся догадок о том, что вы имели в виду. Как насчет того, чтобы явным образом выписал пример статического блока инициализации, который вы имеете в виду, и свою альтернативу, чтобы у людей было что-то ясно ответить? –