10

Can I do it with reflection or something like that?

Par
  • 155
  • 1
  • 2
  • 6

1 Answers1

10

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.

Bruno Reis
  • 37,201
  • 11
  • 119
  • 156
  • Really? My IDE does it just fine ... – Brian Roach Mar 09 '13 at 06:07
  • @BrianRoach, oh, really? Now, you either ask your IDE to list your classes, then you CTRL+C the list, CTRL+V somewhere in your code (and update manually each time you add a new class), or the fact that your IDE knows it is completely useless for the code you are running. Or you try one of the not 100% reliable methods (iterating through your file system or inside a JAR file finding .class files, or using a different approach, such as the one I suggest). Specifically, the IDE knows it is dealing with a file system, so it can easily iterate on the files. 100% reliable. Useless on runtime. – Bruno Reis Mar 09 '13 at 06:18
  • Or you could just press ctrl+T and allow an IDE like eclipse to show you the class hierarchy. It is unclear if the OP wants a solution at runtime / compile time. – Deepak Bala Mar 09 '13 at 06:22
  • 1
    @DeepakBala, since he mentions "using reflection", it is quite clear to me that he is looking for a solution in runtime (if this is not the case, as Brian Roach says, use your IDE, and you're done). – Bruno Reis Mar 09 '13 at 06:24
  • 1
    @BrianRoach it is likly that your IDE is scanning not only class files (it knows about through linking/includes and compilation) but also source code parsing. Netbeans for example actually links to the rt.jar. Try doing the same thing with dynamically loaded classes, I bet your IDE wouldn't know about those ;) – MadProgrammer Mar 09 '13 at 07:46
  • It's a shame this isn't possible, a valid scenario to use this for is testing to ensure new classes implementing a sub type are handled by some other class – Stokedout Nov 09 '20 at 09:00