我想从一个单独的Java项目中获取所有包名称,我最好如何使用反射在Java中执行此操作?
我已将项目导入构建路径,并尝试使用下面的代码获取软件包名称。
Package[] pack = Package.getPackages();
答案 0 :(得分:6)
只使用getPackages()
,您实际上无法知道库中的每个包名称,因为它只会列出类加载器已知的包名称。这意味着如果某个类尚未从特定包中加载,那么它将不在列表中。
使用zip文件处理例程打开jar文件,并按目录名读出包。使用此技术,您将发现所有包名称,甚至是那些尚未“使用”的包名称。基本上,包含.class
文件的任何路径都是“包名”。
----编辑为进一步的细节表明没有使用JAR文件---
既然你没有使用JAR文件(为什么不呢?它们真的很棒!),你必须扫描目录。要“查找”目录,您需要切断类路径。获取类路径的方法是:
String classpath = System.getProperty("java.class.path", null);
然后搜索每个“起始点”下面包含.class
文件的所有目录。一旦掌握了所有这些,就可以获得所有软件包。
同样,通过询问类加载器不可能知道所有包,除非你能以某种方式保证类加载器已经加载了所有类(它通常不会加载)。
答案 1 :(得分: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中的包名称以避免重复。
不幸的是,我们不能只使用下面的代码和普通的Reflection对象,而不指定允许对象扫描的自定义配置。
Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);