Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过反射运行suspend方法?_Java_Kotlin_Async Await_Coroutine_Kotlin Coroutines - Fatal编程技术网

Java 如何通过反射运行suspend方法?

Java 如何通过反射运行suspend方法?,java,kotlin,async-await,coroutine,kotlin-coroutines,Java,Kotlin,Async Await,Coroutine,Kotlin Coroutines,有一个协同程序块可以运行挂起函数 但是我通过反射调用函数。这是java风格的调用,显然一个简单的调用是行不通的。 是否有异步运行反射方法的方法?如何等待这个方法 import kotlin.coroutines.experimental.* class TestClass(val InString: String) { suspend fun printString() { println(InString) } } fun launch(context: C

有一个协同程序块可以运行挂起函数

但是我通过反射调用函数。这是java风格的调用,显然一个简单的调用是行不通的。 是否有异步运行反射方法的方法?如何等待这个方法

import kotlin.coroutines.experimental.*

class TestClass(val InString: String) {
    suspend fun printString() {
        println(InString)
    }
}

fun launch(context: CoroutineContext, block: suspend () -> Unit) =
        block.startCoroutine(StandaloneCoroutine(context))

private class StandaloneCoroutine(override val context: CoroutineContext): Continuation<Unit> {
    override fun resume(value: Unit) {}

    override fun resumeWithException(exception: Throwable) {
        val currentThread = Thread.currentThread()
        currentThread.uncaughtExceptionHandler.uncaughtException(currentThread, exception)
    }
}

fun main(args: Array<String>) {
    launch(EmptyCoroutineContext) {
        val a = TestClass("TestString");

        for (method in a.javaClass.methods) {
            if (method.name == "printString")
                method.invoke(a)  // Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments 

        }
    }
}
导入kotlin.coroutines.experimental*
类TestClass(val指令:字符串){
暂停打印字符串(){
打印(安装)
}
}
有趣的启动(上下文:CoroutineContext,block:suspend()->Unit)=
block.start例程(StandaloneCoroutine(上下文))
私有类StandaloneCoroutine(覆盖val上下文:CoroutineContext):继续{
覆盖乐趣恢复(值:单位){}
覆盖有趣的resumeWithException(异常:可丢弃){
val currentThread=Thread.currentThread()
currentThread.uncaughtExceptionHandler.uncaughtException(currentThread,exception)
}
}
趣味主线(args:Array){
启动(EmptyCoroutineContext){
val a=TestClass(“TestString”);
for(a.javaClass.methods中的方法){
if(method.name==“printString”)
调用(a)//线程“main”java.lang.IllegalArgumentException中的异常:参数数目错误
}
}
}

更新

由于Kotlin 1.3反射本机支持通过
KFunction.callSuspend
KFunction.callSuspendBy
调用挂起函数,因此不再需要上述解决方法

原始答案

Kotlin中的每个
suspend
方法都通过CPS转换在JVM上表示,该转换在。Java反射并没有意识到这一点,Kotlin反射目前也并没有提供执行挂起函数调用的方便方法

您必须自己通过helper函数调用CPS转换。为此,我建议实现以下帮助程序:

import java.lang.reflect.Method
import kotlin.coroutines.experimental.intrinsics.*

suspend fun Method.invokeSuspend(obj: Any, vararg args: Any?): Any? =
    suspendCoroutineOrReturn { cont ->
        invoke(obj, *args, cont)
    }

现在,如果将代码中的
invoke
替换为
invokeSuspend
,那么它将像预期的那样工作。

请参见注释:如果您使用的是Kotlin 1.3,您应该将
suspendCoroutineOrReturn
更改为
suspendcoroutineunterceptedorreturn
请注意,函数
kotlin.coroutines.intrinsics.suspendcoroutineunterceptedorreturn
不是intelliJ通过自动导入找到的函数:您必须手动导入它,或者在键入时完全限定它。