是否可以获得实现接口的所有类? [英] Is it possible to get all classes that implementing an interface?

查看:57
本文介绍了是否可以获得实现接口的所有类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以用反射或类似的方法来做吗?

Can I do it with reflection or something like that?

推荐答案

没有 100% 可靠的方法来做你想做的事.原因在于 Java 中类加载的工作方式.

There's no 100% reliable way to do what you want. The reason is because of how class loading works in Java.

Java 中的类是按需"加载的.第一次在代码中引用类(静态或动态),JVM 将使用当前类加载器并尝试加载它.ClassLoader 没有提供可以从中加载的所有类的方法,因此您无法对类进行迭代.

Classes, in Java, are loaded "on demand". The first time a class is referenced in code (either statically or dynamically), the JVM will use the current class loader and try to load it. A ClassLoader has no method that gives all the classes that could be loaded from it, therefore you cannot iterate on classes.

有一些不可靠的解决方法.例如,如果您知道您的 ClassLoader 只会从特定目录或特定 JAR 文件中加载类,那么您可以使用与您的文件系统相关的类来查找可用的.class"文件,然后您可以加载所有内容(这需要时间并且会消耗大量 PermGen,这可能是一个问题——记住你不能轻易卸载一个类!(除非你做一些 ClassLoader 魔法)),并使用反射来过滤实现你的类的类界面.

There are some unreliable workarounds. For instance, if you know your ClassLoader will only ever load classes from inside a specific directory, or a specific JAR file, you can then use the classes related to your file system to find what ".class" files are available, then you can load everything (which takes time and will consume a lot of your PermGen, which might be a problem -- remember that you cannot easily unload a class! (unless you do some ClassLoader magic)), and use reflection to filter the classes implementing your interface.

此解决方法的问题在于,如果您更改部署,它很可能会停止工作.例如,如果您开始部署 JAR 文件,然后您决定使用处理 WAR 文件的 servlet 容器,您的代码可能不再起作用.

The problem with this workaround is that it will most probably stop working if you ever change your deployment. For instance, if you start deploying a JAR file, then later on you decide to use a servlet container that will deal with WAR files, your code might not work anymore.

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

If you really want to try this approach, there's a project called Reflections that might be useful.

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

The most reliable way I've ever implemented this is by using an Annotation Processor. You write an annotation, you annotate your interface, and you write some code that will get executed by the compiler, in compile-time, that will collect the classes implementing your interface and save their names in a resource file. Then you write a class with a method that reads that file and gives you a Class object for each class name listed in that resource file.

这种方法的问题是只有在我的构建过程中编译的类才会被列出(即,如果你发布一个带有接口的库并期望其他人实现你的接口,这种方法将没有用,因为您的代码永远不会知道其他人项目中的类).如果这对你来说足够了,就像对我一样,这个解决方案可以完美地工作.我可以在带有 WAR(爆炸或不爆炸)部署的 Servlet 容器中、在可执行 jar 中使用它,等等.它永远有效.

The problem with this approach is that only classes that are compiled in my build process will get listed (ie, if you publish a library with an interface and expect others to implement your interface, this approach won't be useful, since your code will never know about the class in others' projects). If this is enough for you, as it was for me, this solution works flawlessly. I can use it in Servlet Containers with WAR (exploded or not) deployments, in executable jars, whatever. It will always work.

这篇关于是否可以获得实现接口的所有类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆