Можно ли найти все классы или интерфейсы в данном пакете? (Быстро глядя на, например Package
, казалось бы, нет.)
java
reflection
packages
Jonik
источник
источник
Ответы:
Из-за динамической природы загрузчиков классов это невозможно. Загрузчики классов не обязаны сообщать ВМ, какие классы она может предоставить, вместо этого они просто передают запросы на классы и должны возвращать класс или выдавать исключение.
Однако, если вы пишете свои собственные загрузчики классов или изучаете пути к классам и их jar-файлы, можно найти эту информацию. Это будет через операции файловой системы, а не отражение. Там могут даже быть библиотеки, которые могут помочь вам сделать это.
Если есть классы, которые генерируются или доставляются удаленно, вы не сможете обнаружить эти классы.
Обычный метод - вместо этого где-то зарегистрировать классы, к которым вам нужен доступ, в файле или ссылаться на них в другом классе. Или просто используйте соглашение, когда дело доходит до именования.
Приложение: Библиотека отражений позволит вам искать классы в текущем пути к классам. Может использоваться для получения всех классов в пакете:
источник
Возможно, вам следует взглянуть на библиотеку Reflections с открытым исходным кодом . С его помощью вы можете легко достичь того, что вы хотите.
Сначала настройте индекс отражений (он немного запутанный, поскольку поиск всех классов по умолчанию отключен):
Затем вы можете запросить все объекты в данном пакете:
источник
.addUrls(ClasspathHelper.forJavaClassPath())
вместо этого решил их для меня. Меньше кода!Google Guava 14 включает новый класс
ClassPath
с тремя методами сканирования классов верхнего уровня:getTopLevelClasses()
getTopLevelClasses(String packageName)
getTopLevelClassesRecursive(String packageName)
См.
ClassPath
Javadocs для получения дополнительной информации.источник
ClassPath
он помечен тегом@Beta
, поэтому для некоторых это может быть плохой идеей ...Вы можете использовать этот метод 1, который использует
ClassLoader
.__________
1 Этот метод был первоначально взят с http://snippets.dzone.com/posts/show/4831 , который был заархивирован интернет-архивом, так как он связан с настоящим моментом . Фрагмент также доступен по адресу https://dzone.com/articles/get-all-classes-within-package .
источник
%20
, ноnew File()
конструктор рассматривал это как буквальный знак процента, два ноль. Я исправил это, изменивdirs.add(...)
строку следующим образом:dirs.add(new File(resource.toURI()));
Это также означало, что мне пришлось добавитьURISyntaxException
к предложению бросковgetClasses
весна
Этот пример для Spring 4, но вы также можете найти сканер classpath в более ранних версиях.
Google Guava
Примечание. В версии 14 API по-прежнему помечен как @Beta , так что будьте осторожны в рабочем коде.
источник
ClassPath
класс в Guava также помечен@Beta
: «API, помеченные аннотацией @Beta на уровне класса или метода, могут быть изменены. Они могут быть изменены любым способом или даже удалены в любом основном выпуске. Если ваш код сама библиотека (т. е. она используется в CLASSPATH пользователей вне вашего собственного контроля), вы не должны использовать бета-интерфейсы API, если вы не перепаковываете их ... " code.google.com/p/guava-libraries/#Important_WarningsgetAllClasses()
можно использовать метод.Привет. У меня всегда были некоторые проблемы с решениями выше (и на других сайтах).
Я, как разработчик, программирую аддон для API. API предотвращает использование любых внешних библиотек или сторонних инструментов. Установка также состоит из смеси кода в файлах jar или zip и файлов классов, расположенных непосредственно в некоторых каталогах. Так что мой код должен был работать в любой ситуации. После долгих исследований я нашел метод, который будет работать как минимум в 95% всех возможных установок.
Следующий код в основном метод overkill, который всегда будет работать.
Код:
Этот код сканирует данный пакет для всех включенных в него классов. Это будет работать только для всех классов в текущем
ClassLoader
.Эти три метода предоставляют вам возможность найти все классы в данном пакете.
Вы используете это так:
Объяснение:
Метод сначала получает текущий
ClassLoader
. Затем он выбирает все ресурсы, которые содержат указанный пакет, и повторяет ихURL
. Затем он создаетURLConnection
и определяет, какой тип URl у нас есть. Это может быть каталог (FileURLConnection
) или каталог внутри файла jar или zip (JarURLConnection
). В зависимости от того, какой тип соединения у нас будет вызываться два разных метода.Сначала давайте посмотрим, что произойдет, если это
FileURLConnection
.Сначала проверяется, существует ли переданный файл и является ли он каталогом. Если это так, он проверяет, является ли это файлом класса. Если это так,
Class
объект будет создан и помещен вArrayList
. Если это не файл класса, а каталог, мы просто перебираем его и делаем то же самое. Все остальные дела / файлы будут игнорироваться.Если
URLConnection
это a,JarURLConnection
будет вызван другой частный вспомогательный метод. Этот метод перебирает все записи в архиве zip / jar. Если одна запись является файлом класса и находится внутри пакета,Class
объект будет создан и сохранен вArrayList
.После того, как все ресурсы проанализированы, он (основной метод) возвращает
ArrayList
содержащую все классы в данном пакете, о которыхClassLoader
знает текущий .Если процесс в какой-то момент
ClassNotFoundException
завершится неудачно, будет сгенерирована подробная информация о точной причине.источник
sun.net.www.protocol.file.FileURLConnection
, который генерирует предупреждение во время компиляции («warning: sun.net.www.protocol.file.FileURLConnection является проприетарным API Sun и может быть удален в будущем выпуске»). Есть ли альтернатива использованию этого класса, или предупреждение может быть подавлено с помощью аннотаций?if ( ... instanceof JarURLConnecton) { ... } else { // Asume that the Connection is valid and points to a File }
это то, что я сделал в своем коде для поиска аннотированных классов JPAБез использования каких-либо дополнительных библиотек:
источник
upackage
этоnull
... :(String pack = getPackage().getName();
, то вы должны добавитьpack = pack.replaceAll("[.]", "/");
В общем случае загрузчики классов не позволяют сканировать все классы на пути к классам. Но обычно единственным используемым загрузчиком классов является UrlClassLoader, из которого мы можем извлечь список каталогов и jar-файлов (см. GetURLs ) и открыть их один за другим, чтобы вывести список доступных классов. Этот подход, называемый сканированием пути классов, реализован в Scannotation and Reflections .
Другой подход заключается в использовании Java Pluggable Annotation Processing API для написания процессора аннотаций, который будет собирать все аннотированные классы во время компиляции и создавать файл индекса для использования во время выполнения. Этот механизм реализован в библиотеке ClassIndex :
Обратите внимание, что никаких дополнительных настроек не требуется, поскольку сканирование полностью автоматизировано благодаря компилятору Java, автоматически обнаруживающему любые процессоры, найденные в пути к классам.
источник
В настоящее время наиболее надежным механизмом для перечисления всех классов в данном пакете является ClassGraph , поскольку он обрабатывает максимально широкий массив механизмов спецификации пути к классам , включая новую систему модулей JPMS. (Я автор.)
источник
Вот как я это делаю. Я сканирую все подпапки (подпакеты) и не пытаюсь загрузить анонимные классы:
источник
Я собрал простой проект GitHub, который решает эту проблему:
https://github.com/ddopson/java-class-enumerator
Он должен работать для ОБА файловых путей к классам И для файлов JAR.
Если вы запустите 'make' после проверки проекта, он напечатает это:
Смотрите также мой другой ответ
источник
Да, используя несколько API, вы можете, вот как мне это нравится, я столкнулся с этой проблемой, которую я использовал в hibernate-ядре и должен был найти классы, которые были аннотированы определенной аннотацией.
Сделайте их пользовательской аннотацией, с помощью которой вы отметите, какие классы вы хотите выбрать.
Затем пометьте свой класс как
Сделайте этот служебный класс, который имеет следующий метод
Вызовите метод allFoundClassesAnnotatedWithEntityToBeScanned (), чтобы получить найденный набор классов.
Вам понадобятся библиотеки, указанные ниже.
источник
Вам нужно найти каждую запись загрузчика классов в пути к классам:
Если запись является каталогом, просто посмотрите в правом подкаталоге:
Если запись является файлом, и это - jar, проверьте записи ZIP этого:
Теперь, когда у вас есть все имена классов в пакете, вы можете попробовать загрузить их с отражением и проанализировать, являются ли они классами или интерфейсами и т. Д.
источник
Я пытался использовать библиотеку Reflections, но у меня были некоторые проблемы с ее использованием, и я должен был включить слишком много jar-файлов, чтобы просто получить классы в пакете.
Я опубликую решение, которое я нашел в этом двойном вопросе: Как получить имена всех классов в пакете?
Ответ был написан sp00m ; Я добавил некоторые исправления, чтобы это работало:
Чтобы использовать его, просто вызовите метод find, как sp00n, упомянутый в этом примере: я добавил создание экземпляров классов, если это необходимо.
источник
Я только что написал класс утилит, он включает в себя методы тестирования, вы можете проверить ~
IteratePackageUtil.java:
источник
Решение Александра Бломскёльда не помогло мне в параметризованных тестах
@RunWith(Parameterized.class)
при использовании Maven. Тесты были названы правильно, а также там, где они были найдены, но не выполнены:О подобной проблеме сообщалось здесь .
В моем случае
@Parameters
это создание экземпляров каждого класса в пакете. Тесты хорошо работали при локальном запуске в IDE. Тем не менее, при запуске Maven не было найдено классов с решением Александра Blomskøld.Я справился со следующим фрагментом, вдохновленным комментарием Дэвида Пярссона к ответу Александра Бломскёльда:
источник
Что насчет этого:
Затем вы можете перегрузить функцию:
Если вам нужно проверить это:
Если в вашей IDE нет помощника по импорту:
Оно работает:
от вашей IDE
для файла JAR
без внешних зависимостей
источник
Почти все ответы либо используют,
Reflections
либо считывают файлы классов из файловой системы. Если вы попытаетесь прочитать классы из файловой системы, вы можете получить ошибки, когда упаковываете ваше приложение в JAR или другое. Также вы можете не использовать отдельную библиотеку для этой цели.Вот еще один подход, который является чисто Java и не зависит от файловой системы.
Java 8 не обязательна . Вы можете использовать для циклов вместо потоков. И вы можете проверить это так
источник
ToolProvider.getSystemJavaCompiler()
, этот код не проверяет вложенные пакеты.При условии, что вы не используете динамические загрузчики классов, вы можете искать путь к классам и для каждой записи искать каталог или файл JAR.
источник
Стоит отметить
Если вы хотите иметь список всех классов в некотором пакете, вы можете использовать
Reflection
следующий способ:Это создаст список классов, которые позже вы сможете использовать их по своему желанию.
источник
Это очень возможно, но без дополнительных библиотек, как
Reflections
это сложно ...Это сложно, потому что у вас нет полного инструмента для получения имени класса.
И я беру код моего
ClassFinder
класса:источник
Основываясь на ответе @ Staale и пытаясь не полагаться на сторонние библиотеки, я бы реализовал подход файловой системы, проверив физическое местоположение первого пакета с помощью:
источник
Если вы просто хотите загрузить группу связанных классов, Spring поможет вам.
Spring может создавать список или карту всех классов, которые реализуют данный интерфейс, в одной строке кода. Список или карта будут содержать экземпляры всех классов, которые реализуют этот интерфейс.
При этом в качестве альтернативы загрузке списка классов из файловой системы вместо этого просто реализуйте один и тот же интерфейс во всех классах, которые вы хотите загрузить, независимо от пакета, и используйте Spring, чтобы предоставить вам экземпляры всех из них. Таким образом, вы можете загрузить (и создать экземпляр) все нужные вам классы независимо от того, в каком пакете они находятся.
С другой стороны, если вы хотите иметь их все в пакете, просто включите все классы в этом пакете для реализации данного интерфейса.
источник
plain java: FindAllClassesUsingPlainJavaReflectionTest.java
PS: чтобы упростить шаблоны для обработки ошибок и т. Д., Я использую здесь
vavr
иlombok
библиотекидругие реализации могут быть найдены в моем репозитории GitHub daggerok / java-отражений-найти-аннотированных классов-или-методов
источник
Я не мог найти короткую рабочую стрижку для чего-то такого простого. Итак, вот оно, я сделал это сам, немного повредив:
источник
Если вы находитесь в Spring-Land, вы можете использовать
PathMatchingResourcePatternResolver
;источник
Это невозможно, так как все классы в пакете могут быть не загружены, в то время как вы всегда знаете пакет класса.
источник