Is it possible to find all kotlin
classes in a given package?
I also need only annotated classes but it's not a big deal. Any suggestions ?
Kotlin on the JVM suffers the same issue as Java in this regard due to the implementation of class loaders.
Class loaders are not required to tell the VM which classes it can provide, instead they are just handed requests for classes, and have to return a class or throw an exception.
Source and more information: Can you find all classes in a package using reflection?
To summarize the linked thread, there are a number of solutions that allow you to inspect your current class path.
ClassPath
, which returns ClassInfo
POJO's - not enough for your use case, but useful to know as Guava is available almost everywhere.Here's an example of querying classloader resources, adapted from https://www.javaworld.com/article/2077477/java-tip-113--identify-subclasses-at-runtime.html
Requires Java 8 or higher.
// Call this function using something like:
// findClasses("com.mypackage.mysubpackage")
// Modified from https://www.javaworld.com/article/2077477/java-tip-113--identify-subclasses-at-runtime.html
fun findClasses(pckgname: String) {
// Translate the package name into an absolute path
var name = pckgname
if (!name.startsWith("/")) {
name = "/$name"
}
name = name.replace('.', '/')
// Get a File object for the package
val url: URL = Launcher::class.java.getResource(name)
val directory = File(url.getFile())
println("Finding classes:")
if (directory.exists()) {
// Get the list of the files contained in the package
directory.walk()
.filter { f -> f.isFile() && f.name.contains('$') == false && f.name.endsWith(".class") }
.forEach {
val fullyQualifiedClassName = pckgname +
it.canonicalPath.removePrefix(directory.canonicalPath)
.dropLast(6) // remove .class
.replace('/', '.')
try {
// Try to create an instance of the object
val o = Class.forName(fullyQualifiedClassName).getDeclaredConstructor().newInstance()
if (o is MyInterfaceOrClass) {
println(fullyQualifiedClassName)
// Optionally, make a function call here: o.myFunction()
}
} catch (cnfex: ClassNotFoundException) {
System.err.println(cnfex)
} catch (iex: InstantiationException) {
// We try to instantiate an interface
// or an object that does not have a
// default constructor
} catch (iaex: IllegalAccessException) {
// The class is not public
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With