我可以用反射或类似的方法来做吗?
1 回答
没有 100% 可靠的方法来做你想做的事。原因在于类加载在 Java 中的工作方式。
Java 中的类是“按需”加载的。第一次在代码中引用类时(静态或动态),JVM 将使用当前的类加载器并尝试加载它。ClassLoader 没有提供可以从中加载的所有类的方法,因此您不能迭代类。
有一些不可靠的解决方法。例如,如果您知道您的 ClassLoader 只会从特定目录或特定 JAR 文件中加载类,那么您可以使用与您的文件系统相关的类来查找可用的“.class”文件,然后您可以加载所有内容(这需要时间并且会消耗大量 PermGen,这可能是个问题——记住你不能轻易卸载一个类!(除非你做了一些 ClassLoader 魔法)),并使用反射来过滤实现你的类界面。
这种解决方法的问题在于,如果您更改部署,它很可能会停止工作。例如,如果您开始部署 JAR 文件,然后您决定使用将处理 WAR 文件的 servlet 容器,您的代码可能不再工作。
如果您真的想尝试这种方法,有一个名为Reflections的项目可能会很有用。
我实现过的最可靠的方法是使用 Annotation Processor 。你写一个注解,你注解你的接口,你写一些代码,这些代码将在编译时被编译器执行,这将收集实现你的接口的类并将它们的名称保存在资源文件中。然后,您编写一个类,该类具有读取该文件的方法,并为该资源文件中列出的每个类名提供一个 Class 对象。
这种方法的问题在于,只有在我的构建过程中编译的类才会被列出(即,如果您发布带有接口的库并希望其他人实现您的接口,那么这种方法将没有用,因为您的代码将永远不知道其他项目中的课程)。如果这对您来说已经足够了,就像对我一样,那么这个解决方案可以完美运行。我可以在带有 WAR(爆炸或未爆炸)部署的 Servlet 容器中、在可执行的 jar 中使用它。它会一直有效。