Как узнать, инициализирован ли класс Java - PullRequest
0 голосов
/ 12 августа 2010

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

Class cl = Class.forName("com.example.MyClass", false, getClass().getClassLoader());
// the false argument above indicates that the class should not be initialized
// but how can I check whether it already was?
cl.isInitialized(); // this does not exist, how can I know instead?

Почему я хочу знать, что:

В проекте клиента у нас есть уродливый класс (*) с большим количеством статических членов, которые я хочу проверить.Чтобы тест был предсказуемым, статические члены должны иметь значения по умолчанию, которые устанавливаются при инициализации.Если тестирование JUnit запускает новую JVM для каждого тестового класса, это не проблема: класс загружается заново при каждом выполнении.Но когда я выполняю тесты в Eclipse вместе с другими, одна и та же JVM используется для нескольких тестов, и класс не загружается заново, и у членов больше нет значений по умолчанию.Я хочу иметь возможность решить, имеет ли смысл тест (потому что класс будет только что загружен) или я должен просто вернуться, потому что тест не имеет смысла, если статические члены были изменены.

(*) рефакторинг запланирован, но не только на данный момент

Упрощенная версия класса

public class Settings {
  public static Properties props;
  static{
    props.setProperty("key1", "val1");
    props.setProperty("key2", "val2");
  }
}  

И тестовый класс

public class SettingsTest extends TestCase {
  public void testDefauts() throws Exception {
    Class cl = Class.forName("Settings", false, getClass().getClassLoader());
    if(cl.isInitialized){ // doesn't exist
      // Cannot test default values, because class was already initialized
      return;
    }

    Properties props = Settings.props; // Settings is initialized here
    assertEquals("val1", props.getProperty("key1"));
    assertEquals("val2", props.getProperty("key2"));
  }
}

Ответы [ 2 ]

1 голос
/ 12 августа 2010

Статические инициализаторы класса (то есть, как называется блок static { ... }) выполняются в первый раз , когда класс загружается загрузчиком классов. Они гарантированно вызываются только один раз и потокобезопасным способом, прежде чем любой другой поток может получить доступ к классу.

Я не уверен, что у вас есть большое значение для модульного теста. Вы проверяете значения, помещенные в объект Properties блоком static {...}. Разве не просто увидеть, что представляют собой значения по умолчанию / исходные, просто основываясь на коде самого класса Settings? Другими словами, вы тестируете логику, которая не может дать сбой, если кто-то не изменит значения по умолчанию.

Я думаю, что вам гораздо лучше просто убрать злобность статических блоков, объекта статических свойств, который (звучит как) модифицируют другие потоки / классы и т. Д .; вместо того, чтобы тратить много времени, пытаясь найти достойный способ модульного тестирования некрасивого кода.

0 голосов
/ 12 августа 2010

Class.forName () инициализирует его , но вы можете назвать его в способом, который не .В любом случае вы можете узнать, была ли она инициализирована.

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

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

public class UglyClass {
    static {
        AnotherUglyClass.uglyClassInitialized = true;
    }
}

public class AnotherUglyClass {
    public static boolean uglyClassInitialized = false;
}

Я уже говорил, что это уродливо?:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...