Снова вызвать статический инициализатор

После загрузки класса есть ли способ снова вызвать статические инициализаторы?

public class Foo {

    static {
        System.out.println("bar");
    }

}

Редактировать:

Мне нужно вызвать статический инициализатор, потому что я не писал исходный класс, а логика, которую мне нужно вызвать, реализована в статическом инициализаторе.


person Kalecser    schedule 25.03.2009    source источник


Ответы (6)


Одно обстоятельство, при котором логика будет выполняться более одного раза, — это если класс загружается несколько раз разными загрузчиками классов. Обратите внимание, что в данном случае это по существу разные классы.

Однако, как правило, это разовые сделки. Если вы хотите иметь возможность вызывать логику несколько раз, сделайте то, что предложили другие, и поместите ее в статический метод.

person McDowell    schedule 25.03.2009
comment
Я пытался найти ссылку на загрузчики классов, но не смог найти хорошую. У тебя есть одна? - person Michael Myers; 25.03.2009
comment
Увы, нет. Мои знания собраны из спецификации VM, javadoc, руководств по серверу и различных интернет-источников. Вы могли бы сделать хуже, чем гуглить developerWorks и ClassLoader. - person McDowell; 25.03.2009
comment
В ответе здесь есть небольшой пример загрузчика классов: /вопросы/33040829/ - person twitchdotcom slash KANJICODER; 10.07.2018

Поместите код инициализации в отдельный общедоступный статический метод, чтобы вы могли вызывать его из статического инициализатора и откуда угодно?

person Daniel Earwicker    schedule 25.03.2009
comment
Я не могу изменить код. Он находится в сторонней библиотеке, и я не собираюсь создавать свой собственный дистрибутив с кодом в обычном статическом методе. :) Решение, которое я использовал, заключалось в том, чтобы скопировать и вставить код в другой класс, чтобы он мог быть в обычном статическом методе. Но мне это не понравилось. СУХОЙ - person Kalecser; 26.03.2009
comment
Хм... тогда мой следующий вопрос: почему этот сторонний класс имеет логику в статическом инициализаторе, который вы, возможно, захотите повторно вызвать?! - person Daniel Earwicker; 26.03.2009
comment
Он загрузит и обработает файл конфигурации XML в статическом инициализаторе, я хочу перезагрузить xml. - person Kalecser; 26.03.2009
comment
Статический инициализатор имеет 70 + LOC. - person Kalecser; 26.03.2009
comment
Эх... сочувствую тебе! :) - person Daniel Earwicker; 26.03.2009

Я согласен с ответом Эрвикера. Просто извлеките статическую инициализацию в отдельный статический метод.

public class Foo {

    static {
        Foo.initialize();
    }

    public static void initialize() {
        System.out.println("bar");
    }

}
person bruno conde    schedule 25.03.2009
comment
Почему минус? Может ли человек, который меня минусовал, объяснить, почему? - person bruno conde; 26.03.2009

В случае, если вы действительно хотите получить точный ответ на свой точный вопрос, ответ - нет. Невозможно вызвать статический инициализатор или instanceInitializer через отражение.

В документах четко сказано:

для getDeclaredMethod(String name) :

Если имя «‹init›» или «‹clinit›», возникает исключение NoSuchMethodException.

для getDeclaredMethods() :

Метод инициализации класса не включается в возвращаемый массив.

Так что нет, его невозможно вызвать даже через отражение.

person Snicolas    schedule 03.10.2013

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

public class OldBadLibraryClass {
   static {
      System.out.println("oldBadLibrary static init");
   }
}

//next file

public class MyBetterClass extends OldBadLibraryClass {
   static {
      System.out.println("MyBetterClass init");
   }
}


public class Test {
   public static void main(String[] args) {
      new MyBetterClass();
   }
}

посмотрите, печатается ли вышеприведенное в том порядке, в котором вы ожидаете. На моей машине это сработало.

Хотя это полностью взлом, и довольно хрупкий. Действительно, было бы намного лучше изменить старый класс, добавив в него метод init(), который можно было бы переопределить.

person Chii    schedule 26.03.2009

Здесь https://stackoverflow.com/a/19302726/2300018 мой пост, где я повторно загружаю служебный класс для повторного запуска статического инициализатора для модульного тестирования.

person André    schedule 19.11.2014