Я знаю как помехи init кладка блоков.
Может любой говорить мне некоторое типичное использование его.
Если вы хотите инициализировать одну или несколько статических переменных в одном месте
Это полезно, потому что вы можете применить обработку исключений, что невозможно с встроенная инициализация.
Например:
public static ImageIcon defaultIcon = ImageIO.read(..);
можно инициализировать с помощью
public static ImageIcon defaultIcon;
static {
try {
defaultIcon = ImageIO.read(..);
} catch (IOException ex){
System.out.println("No default icon available");
}
}
Другое приложение - комплексная инициализация. Например, если элемент требует инициализации более одной строки кода. Допустим, у вас есть конфигурация:
public static Configuration configuration;
static {
confuguration = new Configuration();
configuration.setSomething(..);
configuration.setSomethingElse(..);
...
}
Третье использование - инициализация некоторой внешней инфраструктуры API. Один пример из моего текущего проекта:
static {
org.apache.xml.security.Init.init();
}
Но, как заметил Николай Голубев, статические блоки инициализации делают код менее читабельным, поэтому используйте их с осторожностью. статические методы делают то же самое более прозрачно.
Просто старайтесь избегать использования статического блока инициализации. Вместо этого вы можете использовать частные статические функции инициализации, которые сделают ваш код более чистым.
Я буду ссылаться на @Bozho для примеров.
Не делайте
public static Configuration configuration;
static {
confuguration = new Configuration();
configuration.setSomething(..);
configuration.setSomethingElse(..);
...
}
вместо этого
public static Configuration configuration = createConfiguration();
или
public static Configuration configuration = YourConfiguration.create();
Проще говоря - архитектура - это теория, структура реализации.
-121--1287971-Они часто используются в сочетании с кодом JNI , чтобы гарантировать, что требуемая нативная библиотека загружена:
class MyJniConnection {
public static native void myJniCall();
static {
System.load("native.dll");
}
}
Их можно использовать для создания DSL, как это делает JMock. Например, чтобы задать ожидание того, что пользователь будет сохранен в базе данных:
Mockery context = new Mockery();
final Database database = context.mock(Database.class);
...
context.checking(new Expectations() {{
oneOf(database).save(user);
}});
// Rest of the test
Почему вам нужен Class.forName ()
для загрузки драйвера в память. Ответ прост. Как указано в спецификациях JDBC, все драйверы JDBC
имеют статический блок для регистрации в DriverManager
, как только загружается класс Driver
. Примерно так:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
Итак, когда вы пишете (например, с драйвером MySQL здесь):
Class.forName("org.gjt.mm.mysql.Driver");
Загрузчик классов пытается загрузить и связать класс org.gjt.mm.mysql.Driver
и , в случае успеха выполняется блок статической инициализации, и Driver
регистрируется в DriverManager
.