For example, there is an interface "Apartment".
You need to go through all types of apartments that inherit the "Apartment" interface, (one, two, three, etc.) and, say, add them to the ArrayList .
Is it possible to do this? If so, how?
For example, there is an interface "Apartment".
You need to go through all types of apartments that inherit the "Apartment" interface, (one, two, three, etc.) and, say, add them to the ArrayList .
Is it possible to do this? If so, how?
It is realizable. This can even be useful when you write some 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 it happens, for example, in JDBC) is unacceptable for some reason.
In general, you need:
Immediately you should understand: either you know (require) which constructor will be implemented in all classes, or 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. Fortunately, there is an excellent Reflections library that allows you to do this in two lines of code. Suppose 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, 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 frameworks, then there is a chance that you are somehow wrong, breaking OOP, trying to solve a completely different problem .
Alternative implementations of the CLASSPATH scanner:
The following method finds all classes located in the specified jar archive that implement a specific interface:
Collection<Class<?>> getAllInterfaceImplementations(String pathToJar, Class<?> interfaceType) throws Exception { JarFile jarFile = new JarFile(pathToJar); Enumeration<JarEntry> e = jarFile.entries(); URL[] urls = {new URL("jar:file:" + pathToJar + "!/")}; URLClassLoader cl = URLClassLoader.newInstance(urls); Collection<Class<?>> classes = new ArrayList<>(); while (e.hasMoreElements()) { JarEntry je = e.nextElement(); if (je.isDirectory() || !je.getName().endsWith(".class")) continue; String className = je.getName().substring(0, je.getName().length() - ".class".length()); className = className.replace('/', '.'); Class type = cl.loadClass(className); if (interfaceType.isAssignableFrom(type)) classes.add(type); } return classes; } Use this:
String pathToJar = "<путь до JAVA_HOME>/rt.jar"; for (Class<?> type : getAllInterfaceImplementations(pathToJar, Collection.class)) System.out.println(type.getName()); Source: https://ru.stackoverflow.com/questions/618810/
All Articles