如何使用kotlin中的反射查找包中的所有类

时间:2017-02-22 20:37:43

标签: kotlin

是否可以找到给定包中的所有kotlin类?

我也只需要注释类,但这不是什么大问题。有什么建议吗?

2 个答案:

答案 0 :(得分:11)

由于类加载器的实现,JVM上的Kotlin在这方面遇到了与Java相同的问题。

  

类加载器不需要告诉VM它可以提供哪些类,而只需要处理类的请求,并且必须返回一个类或抛出异常。

来源和更多信息:Can you find all classes in a package using reflection?

为了总结链接的线程,有许多解决方案可以让您检查当前的类路径。

  • Reflections库非常简单,并且具有许多其他功能,例如获取类的所有子类型,使用某些注释获取所有类型/成员注释,可选地与注释参数匹配等等。
  • GuavaClassPath,返回ClassInfo POJO - 对您的用例来说还不够,但有用的是知道Guava几乎无处不在。
  • 通过查询类加载器资源和代码源来编写自己的代码。除非您绝对无法添加库依赖项,否则不建议使用此路由。

答案 1 :(得分:0)

下面是查询类加载器资源的示例,该示例改编自https://www.javaworld.com/article/2077477/java-tip-113--identify-subclasses-at-runtime.html

需要Java 8或更高版本。

// 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
                }
            }
    }
}