Класс недоступен после использования ClassLoader
Если я загружаю класс из файла во время выполнения, используя URLClassLoader:
ClassLoader classLoader = new URLClassLoader(new URL[] { classesUrl }, getClass().getClassLoader());
String name = fileName.replace("\\", ".").replace("/", ".").substring(0, s.lastIndexOf("."));
System.out.println("loading class " + name);
Class c = classLoader.loadClass(name);
System.out.println("loaded " + c.getCanonicalName()); // 1
Это похоже на работу - вывод на 1
является loaded com.robert.test.NumberUtil
,
Если я тогда попытаюсь создать экземпляр этого класса, используя
Class.forName("com.robert.test.NumberUtil");
Я получаю ClassNotFoundException: com.robert.test.NumberTest
, Возможно ли то, что я пытаюсь сделать? Или я должен использовать класс в 1
(т.е. использовать объект, возвращенный из classLoader.loadClass()
и как только он выйдет за рамки его перезагрузки?).
2 ответа
Я работал над этим. Я пытался скомпилировать тесты JUnit, затем загрузить сгенерированные классы и запустить любые классы с пометкой @RunWith(Suite.class)
, но когда я попытался передать классы в JUnitCore, загруженные классы, похоже, потерялись.
В любом случае, поскольку это все равно для пользовательской задачи Ant, я использовал класс Ant JUnitTask и использовал канонические имена классов для запуска и добавил скомпилированный тестовый каталог в путь к классу JUnitTask.
Class.forName()
не создает новый экземпляр вашего класса, он просто пытается найти Class
объект для этого класса. Чтобы создать новый экземпляр, вы можете использовать newInstance() для некоторого объекта Class:
Object something = c.newInstance(); // use proper type instead of Object!
Это работает только для создания экземпляров классов с конструктором по умолчанию; в противном случае вы должны использовать отражение для создания объекта.
Также обратите внимание, что создание нового ClassLoader не сразу влияет на поведение загрузки классов. Для вашего примера выше, вы должны были вызвать
Class.forName("com.robert.test.NumberUtil", true, c); // pass explicit ClassLoader
Чтобы ваш ClassLoader заменил текущий ClassLoader, вы можете сказать,
Thread.currentThread().setContextClassLoader(c)