2012-12-19 64 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