Kotlin使用基于堆栈的常规调用约定和
连续传球风格
CPS变换
总的来说
suspend fun
s通过添加一个隐式参数,可以使用该对象从调用函数的位置继续程序。这就是Kotlin如何成功地实现在函数体中暂停执行的技巧:它提取continuation对象,将其保存在某个地方,然后使函数返回(还没有生成其值)。稍后,它可以通过调用continuation对象来实现跳入函数体中间的效果。
continuation基本上是一个回调对象,就像那些熟悉的异步javaapi一样。suspendable函数不返回其结果,而是将其结果传递给continuation。打电话给
在java中,您必须创建这样一个回调。下面是一个例子:
Continuation<List<String>> myCont = new Continuation<List<String>>() {
@Override public void resume(List<String> result) {
System.out.println("Result of getName is " + result);
}
@Override public void resumeWithException(Throwable throwable) {
throwable.printStackTrace();
}
@NotNull @Override public CoroutineContext getContext() {
return Unconfined.INSTANCE;
}
};
resumeWith(result: Result<T>)
哪里
Result
是结果类型和
internal class Failure
我们还要创建
FileSystem
接口:
class MockFs : FileSystem {
override suspend fun getName(path: Path): List<String> {
suspendCoroutine<Unit> {
println("getName suspended")
}
println("getName resumed")
return listOf("usr", "opt")
}
}
现在我们准备从Java调用它:
Object result = new MockFs().getName(Paths.get(""), myCont);
System.out.println("getName returned " + result);
getName suspended
getName returned
kotlin.coroutines.experimental.intrinsics.CoroutineSuspendedMarker@6ce253f1
getName()
返回一个特殊的标记对象,该对象表示函数被挂起。函数将在恢复后将其实际结果传递给回调。
MockFs
所以我们可以进入下一页:
class MockFs : FileSystem {
var continuation : Continuation<Unit>? = null
override suspend fun getName(path: Path): List<String> {
suspendCoroutine<Unit> {
continuation = it
println("getName suspended")
}
println("getName resumed")
return listOf("usr", "opt")
}
}
MockFs mockFs = new MockFs();
mockFs.getName(Paths.get(""), myCont);
mockFs.getContinuation().resume(Unit.INSTANCE);
这将打印
getName suspended
getName resumed
Result of getName is [usr, opt]
一个
也可以直接返回结果。例如,用这个
模型
class MockFs : FileSystem {
override suspend fun getName(path: Path) = listOf("usr", "opt")
}
在Java中我们可以说
System.out.println(new MockFs().getName(Paths.get(""), myCont));
[usr, opt]
. 我们甚至可以通过一个空的
Continuation
.
Object retVal = mockFs.getName(Paths.get(""), myCont);
if (retVal != IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
myCont.resume((List<String>) retVal);
}
否则,必须复制处理函数结果的代码。