我正在构建一个Java应用程序,其中包含多个不同的包。我想要以编程方式确定应用程序中以特定前缀开头的哪些包存在。是否有任何方法可以使用Java反射API来实现这一点?我没有看到与反射API相关的任何内容。
示例:
com.app.controls.text
com.app.controls.picker
com.app.controls.date
etc
我希望通过了解前缀“com.app.controls”并理解未来可能集成的新包来列举所有这些。
谢谢!
我正在构建一个Java应用程序,其中包含多个不同的包。我想要以编程方式确定应用程序中以特定前缀开头的哪些包存在。是否有任何方法可以使用Java反射API来实现这一点?我没有看到与反射API相关的任何内容。
示例:
com.app.controls.text
com.app.controls.picker
com.app.controls.date
etc
我希望通过了解前缀“com.app.controls”并理解未来可能集成的新包来列举所有这些。
谢谢!
public List<String> findPackageNamesStartingWith(String prefix) {
return Package.getPackages().stream()
.map(Package::getName)
.filter(n -> n.startsWith(prefix))
.collect(toList());
}
请注意,这种技术只会返回当前类加载器中定义的软件包。如果您需要来自不同类加载器的软件包,则有一些选项:
安排事情以便您的程序可以从该类加载器内部运行上述代码。这需要对代码库进行某种组织,这可能可行也可能不可行。
使用反射调用适当类加载器上的(通常受保护的)方法getPackages()。如果程序在安全管理器下运行,则无法使用此方法。
基于肖恩的答案,利用反射获取包列表 - 可能忽略空包:
/**
* 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;
}
Package.getPackages()
返回一个数组。你需要使用Arrays.stream(Package.getPackages())
代替Package.getPackages().stream()
。 - wickund