Есть ли способ заставить загрузчик классов загрузить пакет, даже если ни один из его классов не был загружен?

StackOverflow https://stackoverflow.com/questions/1816730

Вопрос

Допустим, у базы Java-кода есть пакет с именем " com.example ".

Во время выполнения мы можем получить этот пакет, позвонив

Package p = Package.getPackage( "com.example" ); //(returns null)

или даже получить список всех пакетов, позвонив

Packages[] ps = Package.getPackages();

Проблема в том, что если ClassLoader еще не загрузил какой-либо класс из пакета, он не будет доступен для этих вызовов функций. Мы можем принудительно загрузить пакет, сначала загрузив один из классов в пакете, например так:

this.getClass().getClassLoader().loadClass( "com.example.SomeClass" );
Package p = Package.getPackage( "com.example" ); //(returns non-null)

Однако, это хакерство и требует заранее знать имя некоторого класса, который принадлежит пакету.

Итак, вопрос в том, есть ли способ получить экземпляр Package по имени, независимо от того, что ClassLoader что-то сделал? Насколько точны мои предположения о том, как классная загрузка / пакеты работают в этой ситуации?

Это было полезно?

Решение

Полагаю, вам это нужно, потому что вам нужно проверить его аннотации. В противном случае вас не заинтересует ссылка на пакет, в которой используются только операции доступа к аннотациям. Это приводит к предположению, что у вас также есть определенный package-info.java с некоторыми аннотациями.

Если вы выберете java.lang.Package , вы увидите, что getPackageInfo просто загружает класс информации о пакете как обычный класс.

У меня была та же проблема, и я нашел это решение.

public static Package getPackage(String packageName) throws ClassNotFoundException {
    Class.forName(packageName+".package-info"); // makes sure package info exist and that the class loader already knows about the package
    return Package.getPackage(packageName);
}

Другие советы

В качестве альтернативы вы можете использовать корневой каталог класса в качестве отправной точки и пройтись по всем * .class-файлам и подкаталогам. Это будет работать только в том случае, если вы знаете, где все ваши файлы .class будут находиться заранее.

Причиной всего этого является то, что Java имеет динамическую загрузку классов, поэтому классы можно загружать во время выполнения из мест, неизвестных во время компиляции или даже во время запуска. Поэтому концепция пакета - это просто пространство имен для загруженных классов, а не каталог, который вы можете использовать для их поиска.

Боюсь, что ваши предположения не верны. Загрузчики классов ведут бухучет по мере загрузки классов.

Вы можете передать подстановочный знак ClassLoader.getResources и заставить его подобрать классы в пакете, что, в свою очередь, сделает всю работу.

Вы можете создать свой собственный ClassLoader, который вызывает definePackage , но это не поможет вам с обычными ванильными загрузчиками классов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top