Java反射 - 获取包列表

16

我正在构建一个Java应用程序,其中包含多个不同的包。我想要以编程方式确定应用程序中以特定前缀开头的哪些包存在。是否有任何方法可以使用Java反射API来实现这一点?我没有看到与反射API相关的任何内容。

示例:

com.app.controls.text
com.app.controls.picker
com.app.controls.date
etc

我希望通过了解前缀“com.app.controls”并理解未来可能集成的新包来列举所有这些。

谢谢!

2个回答

23
你可以使用Package.getPackages()来实现这一点,它会返回一个包含当前类加载器所知所有包的数组。你需要手动遍历数组并使用getName()方法找到具有适当前缀的包。
下面是一个快速示例:
public List<String> findPackageNamesStartingWith(String prefix) {
    return Package.getPackages().stream()
        .map(Package::getName)
        .filter(n -> n.startsWith(prefix))
        .collect(toList());
}

请注意,这种技术只会返回当前类加载器中定义的软件包。如果您需要来自不同类加载器的软件包,则有一些选项:

  1. 安排事情以便您的程序可以从该类加载器内部运行上述代码。这需要对代码库进行某种组织,这可能可行也可能不可行。

  2. 使用反射调用适当类加载器上的(通常受保护的)方法getPackages()。如果程序在安全管理器下运行,则无法使用此方法。


很遗憾,这些包在当前类加载器中无法识别。还有其他可能的方法吗? - Derek Gebhard
除非明确列出它们,否则通常不会。 - Louis Wasserman
@DerekGebhard:我想到了两种可能性。我已经将它们添加到答案中。 - Sean Reilly
Package.getPackages() 返回一个数组。你需要使用 Arrays.stream(Package.getPackages()) 代替 Package.getPackages().stream() - wickund

0

基于肖恩的答案,利用反射获取包列表 - 可能忽略空包:

/**
 * Finds all package names starting with prefix
 * @return Set of package names
 */
public Set<String> findAllPackagesStartingWith(String prefix) {
    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) {
        String packageName = classInstance.getPackage().getName();
        if (packageName.startsWith(prefix)) {
            packageNameSet.add(packageName);
        }
    }
    return packageNameSet;
}

这些类在我的本地库中大多数都不存在。你是在使用第三方吗? - Lord Farquaad
@LordFarquaad 这是一个旧的回复(2014年1月),我猜你使用的Java版本相对于当时我使用的版本应该是比较新的。 - BLuEGoD

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