К сожалению, Java не предоставляет простой способ перечисления классов в «родной» JRE. Это оставляет вам несколько вариантов: (а) для любого заданного файла JAR вы можете перечислить записи внутри этого файла JAR, найти .class
файлы, а затем определить, какой класс Java представляет каждый .class
файл; или (б) вы можете использовать библиотеку, которая сделает это за вас.
Вариант (а): сканирование файлов JAR вручную
В этом варианте мы заполним classNames
список всех классов Java, содержащихся в файле jar по адресу /path/to/jar/file.jar
.
List<String> classNames = new ArrayList<String>();
ZipInputStream zip = new ZipInputStream(new FileInputStream("/path/to/jar/file.jar"));
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
// This ZipEntry represents a class. Now, what class does it represent?
String className = entry.getName().replace('/', '.'); // including ".class"
classNames.add(className.substring(0, className.length() - ".class".length()));
}
}
Вариант (б): Использование специализированных библиотек отражений
гуайява
У Guava было ClassPath
по крайней мере 14.0, что я использовал и любил. Приятно то, ClassPath
что он не загружает найденные классы, что важно, когда вы сканируете большое количество классов.
ClassPath cp=ClassPath.from(Thread.currentThread().getContextClassLoader());
for(ClassPath.ClassInfo info : cp.getTopLevelClassesRecurusive("my.package.name")) {
// Do stuff with classes here...
}
Размышления
Я лично не использовал библиотеку Reflections , но она мне понравилась. На веб-сайте представлены отличные примеры, например, этот быстрый способ загрузки всех классов в пакет, предоставляемый любым файлом JAR, который также может быть полезен для вашего приложения.
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(SomeAnnotation.class);