Есть ли способ заставить загрузчик классов загрузить пакет, даже если ни один из его классов не был загружен? - PullRequest
15 голосов
/ 29 ноября 2009

Допустим, у базы 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 что-то сделал? Насколько точны мои предположения о том, как классная загрузка / пакеты работают в этой ситуации?

Ответы [ 3 ]

11 голосов
/ 30 ноября 2009

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

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

5 голосов
/ 15 марта 2015

Полагаю, вам это нужно, потому что вам нужно проверить его аннотации. В противном случае вас не заинтересует ссылка на пакет, в которой используются только операции доступа к аннотациям. Это приводит к предположению, что у вас также есть определенный 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);
}
5 голосов
/ 29 ноября 2009

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

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

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

...