2012-12-19 38 views
11

我正在构建一个具有许多不同软件包的Java应用程序。我希望能够以编程方式告诉应用程序中存在哪些以特定预修补程序开始的软件包。无论如何用Java反射API来做到这一点?我没有看到任何与反射apis相关的东西。Java反射 - 获取软件包列表

例子:

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

我想知道前缀“com.app.controls”和理解一个新的包可能会被整合在未来枚举所有的这些。

谢谢!

回答

16

您可以通过使用Package.getPackages()来完成此操作,该操作返回当前类加载器已知的所有包的数组。您必须手动循环访问数组,然后使用getName()找到具有适当前缀的数组。

这里有一个简单的例子:

public List<String> findPackageNamesStartingWith(String prefix) { 
    List<String> result = new ArrayList<>(); 
    for(Package p : Package.getPackages()) { 
     if (p.getName().startsWith(prefix)) { 
      result.add(p.getName()); 
     } 
    } 
    return result; 
} 

注意,这种技术将只返回在当前的类加载器定义的包。如果你需要从不同的类加载器包,也有一些选项:

  1. 安排事情,所以,你的程序可以从类加载器中运行上面的代码。这需要一个特定的组织到您的代码库,这可能或不可行。

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

+0

不幸的是,包不知道当前的类加载器。有没有其他可能的方法? –

+0

可能不是,除了明确列出它们。 –

+0

@DerekGebhard:想到两种可能性。我已将它们添加到答案中。 –

0

从反射的POV几乎不存在包,除了在类加载器中它们是非常隐蔽的。

0

基于Sean's answer并使用反射来获取包的列表 - 可能忽略空的:

/** 
* 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; 
} 
+0

不适用于分装 – cyril