This question already has an answer here:
-
Can you find all classes in a package using reflection?
23 answers
I have a String with some value. I want to iterate over all classes in a package calling a specific method, and if the value returned by the method is equals the value in my String, create an object of that class.
I want do this in a dynamic way, so if I add a class in this package, it will automatically be in the iteration.
Is possible do this? If not, there is a way to do what I want?
I was expecting something like.
for(Class clazz: SomeClass.listClasses("org.package")){
//code here
}
No, this is not possible in a totally reliable way; however, it may be practical to implement in many cases.
Due to the flexibility of Java class loaders, the classes defined under a particular package may not be known at runtime (e.g. consider a special classloader which defines classes on-the-fly, perhaps by loading them from the network, or compiling them ad-hoc). As such, there is no standard Java API which allows you to list the classes in a package.
Practically speaking, however, you could do some tricks by searching the classpath for all class and JAR files, building a collection of fully-qualified class names, and searching them as desired. This strategy would work fine if you are sure that no active classloader will behave as described in the previous paragraph. For example (Java pseudocode):
Map<String, Set<String>> classesInPackage = new HashMap();
for (String entry : eachClasspathEntry()) {
if (isClassFile(entry)) {
String packageName = getPackageName(entry);
if (!classesInPackage.containsKey(packageName)) {
classesInPackage.put(packageName, new HashSet<String>());
}
classesInPackage.get(packageName).add(getClassName(entry));
} else if (isJarOrZipFile(entry)) {
// Do the same for each JAR/ZIP file entry...
}
}
classesInPackage.get("com.foo.bar"); // => Set<String> of each class...
I can think of two ways to solve what I think your problem is, though neither truly iterate over all classes in a package.
One is to create a separate file that lists classes on which that specific method should be called. This is quite easy to implement. You might have some work creating the file, but that could be automated.
The second option is to look for .class files at some well known place -- say a single folder or a set of folders -- and guess what the class name would be and load it. If this is a simple development process, the classfiles from a single package are probably in a single directory.
Yes, but not as a general case solution. You'll have to package up your code and invoke the JVM in specific way. Specifically, you'll need to create an Instrumentation agent, and call java.lang.instrument.Instrumentation.getAllLoadedClasses()
.
The package documentation for java.lang.instrument
has lots of details on how to create and instantiate an agent.