使用Java Reflection获取包名

3

我想从一个独立的Java项目中获取所有包名,使用Java反射最好,你能怎么做呢?

我已将该项目导入到我的构建路径中,并尝试使用以下代码来获取包名:

Package[] pack = Package.getPackages();

编辑:我没有使用jar文件,我只是将项目导入,因为它将在同一目录中。我只需要我创建的包,特别是以某个目录开头的包。


我想从一个独立的Java项目中获取所有包名,最好使用反射,在Java中应该如何实现?所有这些骚操作会给终端用户带来什么?你试图提供什么应用程序特性? - Andrew Thompson
2个回答

6
您无法仅通过使用 getPackages() 来了解库中的每个包名称,因为它只会列出类加载器已知的包。这意味着,如果尚未从特定包加载类,则该类将不在列表中。
使用zip文件处理例程打开jar文件,并通过目录名称读取出包。使用此技术,您将发现所有包名称,甚至那些尚未“使用”。基本上,任何包含 .class 文件的路径都是一个“包名称”。
---- 根据进一步细节进行编辑,指示未使用JAR文件---
由于您未使用JAR文件(为什么不使用?它们真的很好!),因此您将需要扫描目录。要“查找”目录,您需要拆分类路径。获取类路径的方法是:
 String classpath = System.getProperty("java.class.path", null);

然后您搜索每个“起始点”下包含.class文件的所有目录。一旦您拥有了这些,您就拥有了所有的包。

同样,除非您能够保证类加载器已加载所有类(通常情况下不会),否则无法仅通过询问类加载器来知道所有包。


请查看更新,并考虑将您的类打包成jar文件。 - Edwin Buck

0
只要您不需要空包,类似这样的代码应该可以解决问题:
/**
 * Finds all package names
 * @return Set of package names
 */
public Set<String> findAllPackages() {
    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) {
        packageNameSet.add(classInstance.getPackage().getName());
    }
    return packageNameSet;
}

它会找到所有的类,循环遍历它们并将包名存储在一个Set中以避免重复。
不幸的是,我们不能仅使用下面的代码与普通的Reflections对象一起使用,而需要指定自定义配置以允许对象扫描。
Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接