java - 如何从 Java 使用 Kotlin 反射

标签 java kotlin reflection kotlin-reflect

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

我想从 Java 中的 Kotlin 函数获取 KCallable 并使用它的方法 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)
}

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

编辑:

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

调用的已知信息是:

  • 参数名称
  • 他们的类型
  • 他们的值(value)

编辑 2:

此处不工作 @JvmOverloads 的示例:

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

这里用一个 String 值调用是不明确的。

最佳答案

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

作为文档 states :

Normally, if you write a Kotlin function with default parameter values, it will be visible in Java only as a full signature, with all parameters present. If you wish to expose multiple overloads to Java callers, you can use the @JvmOverloads annotation.

因此,添加此注释后:

@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 互操作的局限性,那么您确实需要在 Java 代码中获取 KCallable 的实例。

我相信没有辅助的 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"
    }
}

关于java - 如何从 Java 使用 Kotlin 反射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64539969/

相关文章:

java - 当第一个参数是具有一个方法的类时,无法用 lambda 替换 SAM 构造函数

c# - 静态成员和接口(interface)

java - 为什么 java.lang.Object.getClass() (和反射)比平时慢?

java - 有没有办法将 SQL 查询转换为 liquibase 更改日志格式?

java - Android - 语音解锁手机

android - Unresolved reference : DaggerTestComponent (Kotlin with Dagger for Test)

c# - 使用反射获取类型

java - 用一些消息替换字符串生成器中的 null 或空数据

java - 探戈计划 : Determine whether an IntersectionPointPlaneModelPair is aligned with Gravity

kotlin - 使用 kotlin 进行函数式编程 - 避免 var