Использование статического блока инициализации
Я знаю, как работает статический блок инициализации.
Может кто-нибудь, пожалуйста, скажите мне некоторые типичные использования этого.
7 ответов
Когда вы хотите инициализировать одну или несколько статических переменных в одном месте
Это полезно, потому что вы можете применить обработку исключений, что невозможно при встроенной инициализации.
Например:
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();
Они часто используются в сочетании с кодом JNI для обеспечения загрузки необходимой собственной библиотеки:
class MyJniConnection {
public static native void myJniCall();
static {
System.load("native.dll");
}
}
- Инициализация статического поля коллекции, например Map, List, Set и т. Д.
- Инициализация объекта на основе сеттера, который также является статическим
Драйвер JDBC является популярным примером
Зачем тебе Class.forName()
загрузить драйвер в память. Ответ прост. Как указано в спецификации JDBC, все JDBC Driver
иметь статический блок для регистрации 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
,
Их можно использовать для создания 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
- статический блок:- когда мы хотим выполнить код во время загрузки класса, тогда мы можем поместить код в статический блок...
- init:- когда мы хотим выполнить код во время инициализации объекта класса, тогда мы можем поместить код в блок init....