2013-03-09 110 views
8

我可以用反射或类似的东西来做吗?是否有可能获得实现接口的所有类?

+4

为什么这么多downvotes?这是一个完全有效的问题! – 2013-03-09 06:05:07

+1

可能的重复http://stackoverflow.com/questions/347248,http://stackoverflow.com/questions/435890 – StarPinkER 2013-03-09 06:06:26

+0

尝试[这](http://tinyurl.com/d5ohdr4) – 2013-03-09 06:09:14

回答

9

有没有100%可靠的方法来做你想做的。原因是因为Java中的类加载是如何工作的。

Java中的类按需“加载”。第一次在代码中引用类(静态或动态)时,JVM将使用当前的类加载器并尝试加载它。 ClassLoader没有方法给出所有可以从中加载的类,因此不能迭代类。

有一些不可靠的解决方法。例如,如果您知道您的ClassLoader只会从特定目录或特定的JAR文件中加载类,则可以使用与您的文件系统相关的类来查找可用的“.class”文件,然后您可以加载所有东西(这需要花费时间并且会消耗很多的PermGen,这可能是一个问题 - 记住,你不能轻易地卸载一个类!)(除非你做了一些ClassLoader魔术),并且使用反射来过滤实现你的类接口。

此变通办法的问题是,如果您更改了部署,它很可能会停止工作。例如,如果您开始部署JAR文件,稍后您决定使用将处理WAR文件的servlet容器,那么您的代码可能无法工作。

如果你真的想尝试这种方法,有一个名为Reflections的项目可能会有用。

我曾经实现过的最可靠的方法是使用注释处理器。您编写注释,注释接口,编写一些代码,编译时会执行这些代码,这些代码将收集实现您的接口的类并将其名称保存在资源文件中。然后用一个读取该文件的方法编写一个类,并为该资源文件中列出的每个类名提供一个Class对象。

这种方法的问题是,只有在我的构建过程中编译的类才会被列出(例如,如果您使用接口发布库并期望其他人实现您的接口,则此方法将不会有用,因为你的代码永远不会知道别人项目中的类)。如果这对于你来说已经足够了,就像我一样,这个解决方案完美无瑕。我可以在带有WAR(部署或不部署)的Servlet容器中使用它,在可执行文件中使用它。它会一直工作。

+0

真的吗?我的IDE做得很好... – 2013-03-09 06:07:08

+0

@BrianRoach,哦,真的吗?现在,您可以要求您的IDE列出您的类,然后按CTRL + C列表,在代码中的某处添加CTRL + V(并且每次添加新类时手动更新),或者IDE知道它完全是事实对于您正在运行的代码无用。或者你尝试一种不是100%可靠的方法(迭代你的文件系统,或者在JAR文件中找到.class文件,或者使用不同的方法,比如我建议的方法)。具体来说,IDE知道它正在处理文件系统,因此它可以轻松地迭代文件。 100%可靠。运行时无用。 – 2013-03-09 06:18:04

+0

或者你可以按下ctrl + T,并允许像eclipse这样的IDE向你展示类层次结构。目前还不清楚OP是否需要在运行时/编译时提供解决方案。 – 2013-03-09 06:22:02

相关问题