Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to get all classes that implementing an interface? [duplicate]

Can I do it with reflection or something like that?

like image 865
Par Avatar asked Mar 09 '13 06:03

Par


1 Answers

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

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.

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.

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.

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

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.

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.

like image 79
Bruno Reis Avatar answered Oct 16 '22 14:10

Bruno Reis