首页 > 解决方案 > 将文件路径反映到源目录或 jar 时找不到 Kotlin 类

问题描述

===更新:使用 org.reflections:reflections:0.9.11

希望使用以下行从 Kotlin 源中提取类名列表...

Reflections.getSubTypesOf(Any::class.java)

但是,当我运行以下脚本时,我收到一条消息说没有看到 Kotlin 类文件...

val classLoader = URLClassLoader(this.getDirectoryUrls(), null)
println("retrieved class loader")

val config = getConfig(classLoader)
println("retrieved source config")

val reflections = Reflections(config)
println("retrieved reflections")

// For 3 paths: Reflections took 3 ms to scan 3 urls, producing 0 keys and 0 values

=== 更新:“getDirectoryUrls()”添加的 3 个 url 是包含 kotlin 类源文件的目录。

以下是我的配置...想法?

private fun getConfig(classLoader: ClassLoader): ConfigurationBuilder {
    val config = ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(classLoader))
    //                .setScanners(SubTypesScanner(false), ResourcesScanner())

    if (!packagePath.isNullOrBlank()){
        System.out.println("looking in package [$packagePath]")
        config.filterInputsBy(FilterBuilder().include(FilterBuilder.prefix(packagePath)))
    }

    config.addClassLoader(classLoader)
    config.setScanners(SubTypesScanner(), TypeAnnotationsScanner())

    return config
}

标签: reflectionjarkotlinclassloader

解决方案


SubTypesScanner(false)似乎需要设置才能获得任何类型getSubTypesOf(Any::class.java)(该参数本身代表excludeObjectClass)。查看 Kotlin 类的字节码,您会立即看到,它们实际上看起来与 Java 类相同。那里没有Any-superclass。请注意,KotlinsAny实际上在其他方面也与 Java 非常相似Object(但不一样,请检查以下对 'does Any == Object' 的答案)。因此,我们需要在扫描(ie )Object的子类型时包含 -class 。AnyexcludeObjectClass=false

另一个问题可能是您的URL阵列的设置。我只是使用以下设置反射工具:

val reflections = Reflections(ConfigurationBuilder()
            .addUrls(ClasspathHelper.forPackage("my.test.package"))
            .setScanners(TypeAnnotationsScanner(), SubTypesScanner(false)))

这将解析所有匹配的子类型,并将返回子类型也为Any.

reflections.getSubTypesOf(MyCustomSuperType::class.java).forEach(::println)
reflections.getSubTypesOf(Any::class.java).forEach(::println)

进一步分析:您提到“Kotlin 类文件”......如果这意味着您指向包含.kt-files 的目录,那么这可能是您的问题。尝试使用包含.class-files 的目录。此外,确保类在类路径上。

也许你已经知道了,也许还没有?另请注意,如果您有一个(类)目录,比如说/sample/directory,它在类路径上并且包含一个包,比如说org.example(对应于文件夹结构org/example或完整路径/sample/directory/org/example),那么您必须确保添加URL类似于以下内容:

 YourClass::class.java.classLoader.getResource("")

并不是:

 YourClass::class.java.classLoader.getResource("org.example")
 // nor:
 YourClass::class.java.classLoader.getResource("org/example")

您基本上需要“基本”目录(在示例中/sample/directory或仅从类加载器的视图中""))在其中查找包而不是包本身。如果您提供后者之一,则实际上只会找到URL默认包(在 内/sample/directory/org/example)中的类,但这是一种相当不常见的设置。


推荐阅读