5

除了此处发布的问题:您可以使用反射找到包中的所有类吗?我开始使用 Reflections 库来查找所有子类给定类型的类。源代码如下所示,来自链接的 SO 问题的答案:

Reflections ref = new Reflections(new ConfigurationBuilder()
    .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
    .setUrls(ClasspathHelper.forPackage("org.somepackage"))
    .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("org.somepackage"))));

ref.getSubtypesOf(Object.class);

然而,在不知不觉中使用了这段代码一段时间后,我刚刚发现它只会在这个包中找到子类化另一种类型的类。它不会找到继承外部定义类的类,比如来自另一个用户定义的包。

我不确定如何使用 Reflections 库来解决这个问题。我希望所有将其包声明为“org.somepackage”的类,无论它们的超类型是什么。有什么帮助吗?

4

3 回答 3

6

我编写了一个名为Rebound(与 Reflections 相对)的库,它搜索给定类型和包前缀的子类。如果将前缀设置为空,它将搜索类路径下的每个类,例如

import gigadot.exp.reflects.core.Processor;

Rebound r = new Rebound("");
Set<Class<? extends Processor>> classes = r.getSubClassesOf(Processor.class);

但是您应该小心,因为在类路径中搜索所有内容是一个缓慢的过程。

该库比 Reflections 简单得多,并且可能无法执行您想要的操作。由于我在提交错误报告时感到沮丧,但没有人试图解决这个问题,我写了这篇文章。

于 2012-09-19T16:44:13.960 回答
2

这样做的原因是,

ref.getSubtypesOf(Object.class);

只返回 Object 的直接子类。如果要从扫描的包中获取所有类,则应执行以下操作:

Reflections ref = new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner(false), new ResourcesScanner(), new TypeElementsScanner())
...
Set<String> typeSet = reflections.getStore().getStoreMap().get("TypeElementsScanner").keySet();
HashSet<Class<? extends Object>> classes = Sets.newHashSet(ReflectionUtils.forNames(typeSet, reflections
            .getConfiguration().getClassLoaders()));

This may look a little hackish but it's the only way I found so far. Here's a little explanation of what this does: When Reflections is done with the scanning, it puts all the elements in a multi-value map. In the code example that I pasted, the results are put inside a map with the following keys:

SubTypesScanner, ResourcesScanner, TypeElementsScanner

The ResourceScanner excludes all files ending with .class. The TypeElementsScanner is a map with a key holding the name of a class, and a value of the fields etc. So if you want to get only the class names, you basically get the key set and later on, convert it to a set if classes. The SubTypesScanner is also a map, with a key of all the super classes (including Object and interfaces) and values - the classes implementing/extending those interfaces/classes.

如果您愿意,您也可以使用 SubTypesScanner,通过迭代键集并获取所有值,但是如果某个类实现了一个接口,您将不得不处理重复的实体(因为每个类都扩展 Object)。

希望有帮助。

于 2013-11-04T15:51:41.143 回答
0

就我而言,这段代码可以很好地加载外部 API 的类,但不确定为什么它不适用于像“java.util”这样的内置包。

Reflections reflections = new Reflections(new ConfigurationBuilder()
                .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
                .setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[2])))
                .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("org.reflections"))));
于 2013-03-13T12:21:00.633 回答