Использование статического блока инициализации - PullRequest
9 голосов
/ 03 февраля 2010

Я знаю, как работает статический блок инициализации.
Может кто-нибудь, пожалуйста, скажите мне, как это типично.

Ответы [ 7 ]

10 голосов
/ 03 февраля 2010

Когда вы хотите инициализировать одну или несколько статических переменных в одном месте

Это полезно, потому что вы можете применить обработку исключений, что невозможно при встроенной инициализации.

Например:

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();
}

Но, как отметил Николай Голубев, блоки статической инициализации делают код менее читабельным, поэтому используйте их с осторожностью. статические методы делают то же самое более прозрачно.

5 голосов
/ 03 февраля 2010

Просто попробуйте избежать использования статического блока инициализации. Вместо этого вы можете использовать частные статические функции инициализации, которые сделают ваш код более чистым.

Я буду ссылаться на @Bozho для примеров.

Не делай

public static Configuration configuration;
static {
     confuguration = new Configuration();
     configuration.setSomething(..);
     configuration.setSomethingElse(..);
     ...
}

Используйте вместо

public static Configuration configuration = createConfiguration();

или

public static Configuration configuration = YourConfiguration.create();
3 голосов
/ 03 февраля 2010

Они часто используются вместе с кодом JNI , чтобы обеспечить загрузку необходимой собственной библиотеки:

class MyJniConnection {

    public static native void myJniCall();

    static {
        System.load("native.dll");
    }
}
2 голосов
/ 03 февраля 2010

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.

2 голосов
/ 03 февраля 2010
  • Инициализация статической коллекции поле, как карта, список, набор и т. д.
  • Инициализация статического объекта, который также является статическим
1 голос
/ 03 февраля 2010

Их можно использовать для создания 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
0 голосов
/ 22 мая 2013
  • статический блок: - когда мы хотим выполнить код во время загрузки класса, тогда мы можем поместить код в статический блок ...
  • init: - когда мы хотим выполнить код во время инициализации объекта класса, тогда мы можем поместить код в блок init ....
...