Как заставить class быть инициализированным?

Каков наилучший и самый чистый способ сделать это? В частности, мне нужен код в статическом блоке инициализатора для запуска в этом classе, но я хотел бы сделать это как можно более чистым.

Загрузка! = Инициализация.

Вы хотите, чтобы ваш class был инициализирован (это, в частности, выполнение статических блоков).

Выдержка из спецификации языка Java гласит:

Тип classа или интерфейса T будет инициализирован непосредственно перед первым вхождением> любого из следующих:

  • T – class, и создается экземпляр T.
  • T – class, и статический метод, объявленный T, вызывается.
  • Статическое поле, объявленное T, назначается.
  • Статическое поле, объявленное T, используется, и поле не является постоянной переменной (§4.12.4).
  • T – class верхнего уровня, и выполняется инструкция assert (§14.10), лексически вложенная в T.

Вызов некоторых отражающих методов в classе Class и в пакете java.lang.reflect также вызывает инициализацию classа или интерфейса. Класс или интерфейс не будут инициализированы ни при каких других обстоятельствах.

Doh, anovstrup, уже сказал это: просто создайте пустую статическую функцию init . Обязательно запишите это хорошо … Я лично не вижу никакого варианта использования для этого в контексте хорошо сформированного кода.

Вы можете использовать следующий код для принудительной инициализации classа:

 //... Foo.class ... //OLD CODE ... forceInit(Foo.class) ... //NEW CODE /** * Forces the initialization of the class pertaining to * the specified Class object. * This method does nothing if the class is already * initialized prior to invocation. * * @param klass the class for which to force initialization * @return klass */ public static  Class forceInit(Class klass) { try { Class.forName(klass.getName(), true, klass.getClassLoader()); } catch (ClassNotFoundException e) { throw new AssertionError(e); // Can't happen } return klass; } 
 try { Class.forName(class name as string) } catch(ClassNotFoundException e) { whatever } 

Это должно сделать это.

@Longpoke

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

 package test; public class TestStatic { public static void main(String[] args) { try { Class.forName("test.Static"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } 

При загрузке следующего статического classа:

 package test; public class Static { static { System.out.println("Static Initializer ran..."); } } 

Если статические инициализаторы не выполняются до тех пор, пока не будут выполнены указанные вами условия, то почему этот println выполняется, когда я запускаю свой тест? Это, какие из перечисленных мной условий я встречаю?

Невидимые зависимости между classами не являются хорошей идеей. Я предлагаю переместить код в статическом блоке инициализатора в статический метод и вызвать его непосредственно в зависимом classе. Статический блок инициализатора можно переписать для вызова вновь созданного статического метода.

Одним из решений было бы вызвать статический метод:

 public class A { static { DebugUtils.FLAG_TEST_USER = true; } static void init() {} } 

Затем вызовите A.init() чтобы принудительно инициализировать.

Тем не менее, делать это вообще – это запах кода. Рассмотрите возможность замены статического кода на стандартный конструктор в одноэлементном объекте.

Если вам нужно статически инициализировать что-то в classе, это означает, что на этом должны быть classы клиентов.

Если есть один клиент, или назовем его естественным домом для блока инициализации, я думаю, что было бы самым чистым его инициализировать.

Для случая с множеством равных клиентов может быть хорошей идеей проверить из этих classов, что статическая инициализация в другом classе была успешной. Затем связь документируется, и вы уверены, что class всегда инициализируется до того, как ему понадобится первый клиент.