Question:
For example, there is the "Apartment" interface.
You need to go through all types of apartments that inherit the "Apartment" interface (one, two, three, etc.) and, say, add them to an ArrayList
.
Can this be done? If so, how?
Answer:
This is realizable. It can even be useful when you are writing an extensible framework and do not know in advance what objects you will have to work with, and forcing the user to register classes manually (as happens, for example, in JDBC) is somehow unacceptable.
In general, you need:
- Run CLASSPATH scan
- Check all found classes through reflection on interface / class inheritance.
- Call the constructor through reflection.
It's worth understanding right away: either you know (require) which constructor will be implemented in all classes, or you use the default constructor without parameters (and it is created automatically only if there are no other explicit constructors).
Items 1 and 2 are somewhat tedious to implement manually. Luckily, there is a great library called Reflections that lets you do this in two lines of code. Let's say we are interested in all implementations of the HttpHandler
interface:
Reflections reflections = new Reflections();
Set<Class<? extends HttpHandler>> classes = reflections.getSubTypesOf(HttpHandler.class);
And that's it! Now it remains to iterate over all instances of Class
and call, let's say, a constructor without parameters:
List<HttpHandler> handlers = new ArrayList<>();
for (Class<? extends HttpHandler> clazz : classes) {
try {
handlers.add(clazz.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
System.out.println("Не удалось создать экземпляр: " + clazz.getCanonicalName());
}
}
But!
If you are not yet writing your own frameworks, then there is a possibility that you are somehow wrong, breaking OOP, trying to solve a completely different problem .
Alternative implementations of the CLASSPATH scanner: