首页 > 解决方案 > 如何在 Java 中使用 Kotlin 反射

问题描述

是否可以从 Java 中使用 Kotlin 反射?

我想KCallable从 Java 中的 Kotlin 函数中获取并使用它的方法callBy来调用具有默认参数的方法。

Kotlin 中的示例:

fun test(a: String = "default", b: String): String {
    return "A: $a - B: $b";
}

fun main() {
    val callable: KCallable<*> = ::test
    val parameterB = callable.parameters[1]

    val result = callable.callBy(mapOf(
        parameterB to "test"
    ))

    println(result)
}

甚至可能吗?如果是这样,如何KCallable从 Java 代码中获取实例?

编辑:

我不能@JvmOverloads按照建议使用,因为参数的数量、默认参数及其位置可以是任意的。

已知的调用信息是:

编辑2:

不在这里工作的例子@JvmOverloads

fun test(a: String = "default", b: String = "default"): String {
    return "A: $a - B: $b";
}

String这里用一个值调用是模棱两可的。

标签: javakotlinreflectionkotlin-reflect

解决方案


如果test声明函数的文件是Utils.kt,那么它将被编译到UtilsKt类中。

正如文件所述

通常,如果您使用默认参数值编写 Kotlin 函数,它在 Java 中将仅作为完整签名可见,并且所有参数都存在。如果您希望向 Java 调用者公开多个重载,可以使用 @JvmOverloads 注释。

因此,添加此注释后:

@JvmOverloads 
fun test(a: String = "default", b: String): String {
    return "A: $a - B: $b";
}

test可以使用单个参数从 java 调用方法:

public class ReflectionInterop {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method test = UtilsKt.class.getDeclaredMethod("test", String.class);
        String result = (String) test.invoke(null, "test"); //null used because method is compiled as static, so no instance needed to call it
        System.out.println(result); //Will print "A: default - B: test"
    }
}

编辑

如果您正在寻找一种方法来克服方便的 java 互操作的限制,那么您确实需要KCallable在您的 Java 代码中获取一个实例。

我相信没有辅助 Kotlin 功能是不可能的:

fun testReflection(): KCallable<*> = ::test

它在 Java 中的使用非常简单:

public class ReflectionInterop {
    public static void main(String[] args) {
        KCallable<?> test = UtilsKt.testReflection(); //Assuming it is located in the same `Utils.kt` file
        KParameter parameterB = test.getParameters().get(1);
        String result = (String) test.callBy(new HashMap<>() {{
            put(parameterB, "test");
        }});
        System.out.println(result); //Will print "A: default - B: test"
    }
}

推荐阅读