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