Java Reflection - Получить список пакетов
Я создаю приложение Java, которое имеет несколько разных пакетов. Я хочу иметь возможность сказать программно, какие пакеты существуют в приложении, которые начинаются с определенного предварительного исправления. Есть ли все-таки сделать это с API-интерфейсами Java отражения? Я не видел ничего подобного, связанного с отражением apis.
Пример:
com.app.controls.text
com.app.controls.picker
com.app.controls.date
etc
Я хочу перечислить все это, зная префикс "com.app.controls" и понимая, что новый пакет может быть интегрирован в будущем.
Спасибо!
Ответы
Ответ 1
Вы можете сделать это, используя Package.getPackages(), который возвращает массив всех пакетов, известных текущему загрузчику класса. Вам придется вручную прокручивать массив и находить те, у которых есть соответствующий префикс, используя getName().
Вот пример:
public List<String> findPackageNamesStartingWith(String prefix) {
List<String> result = new ArrayList<>();
for(Package p : Package.getPackages()) {
if (p.getName().startsWith(prefix)) {
result.add(p.getName());
}
}
return result;
}
Обратите внимание, что этот метод возвращает только пакеты, определенные в текущем загрузчике классов. Если вам нужны пакеты из другого загрузчика классов, есть несколько вариантов:
-
Расположите вещи так, чтобы ваша программа могла запускать вышеуказанный код внутри этого загрузчика классов. Это требует определенной организации для вашей базы кода, которая может быть или не быть осуществимой.
-
Используйте отражение, чтобы вызвать метод getPackages() в соответствующем загрузчике классов. Это не будет работать, если программа работает под управлением безопасности.
Ответ 2
Пакеты практически не существуют из POV отражения, они довольно невидимы, за исключением загрузчиков классов.
Ответ 3
Основываясь на Ответ Шона и используя отражение, чтобы получить список пакетов - возможно, игнорируя пустые:
/**
* Finds all package names starting with prefix
* @return Set of package names
*/
public Set<String> findAllPackagesStartingWith(String prefix) {
List<ClassLoader> classLoadersList = new LinkedList<ClassLoader>();
classLoadersList.add(ClasspathHelper.contextClassLoader());
classLoadersList.add(ClasspathHelper.staticClassLoader());
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setScanners(new SubTypesScanner(false), new ResourcesScanner())
.setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[0])))
.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("my.base.package"))));
Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);
Set<String> packageNameSet = new TreeSet<String>();
for (Class classInstance : classes) {
String packageName = classInstance.getPackage().getName();
if (packageName.startsWith(prefix)) {
packageNameSet.add(packageName);
}
}
return packageNameSet;
}