当前位置: 首页 > 知识库问答 >
问题:

科特林暂停娱乐

漆雕奇
2023-03-14

我有静态编程语言界面

interface FileSystem {
    suspend fun getName(path: Path): List<String>
}

我如何从爪哇调用它?什么

Continuation <? super List<String>>

共有1个答案

佟翰林
2023-03-14

Kotlin混合使用常规的基于堆栈的调用约定和连续传递风格(CPS)来实现协同程序。为了实现这一点,它通过添加一个隐式参数对所有的< code>suspend fun执行CPS转换,该参数是一个可以用来从调用函数的地方继续程序的对象。这就是Kotlin设法在函数体内暂停执行的方法:它提取continuation对象,将其保存在某个地方,然后让函数返回(还没有产生它的值)。稍后,它可以通过调用continuation对象来实现跳到函数体中间的效果。

延续基本上是一个回调对象,就像那些从异步JavaAPI中熟悉的对象一样。可挂起函数不会返回其结果,而是将其结果传递给延续。要从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;
    }
};

注意:以上仅适用于实验协程。在最终的API中只有一种恢复方法:resumeBy(结果:结果

让我们也创建一个文件系统接口的模拟实现:

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()返回一个特殊的标记对象,该对象表示函数已暂停。一旦恢复,该函数将把它的实际结果传递给我们的回调。

现在让我们改进< code>MockFs,这样我们就可以访问continuation:

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]

在现实生活中,可挂起函数会使用某种机制在结果可用时恢复自身。例如,如果它是某个异步API调用的包装器,它将注册一个回调。当异步API调用回调时,它会反过来调用我们的延续。您不应该像我们在模拟代码中那样手动恢复它。

< code>suspend fun也可以选择直接返回结果。例如,使用下面的< code>MockFs代码

class MockFs : FileSystem {
    override suspend fun getName(path: Path) = listOf("usr", "opt") 
}

在Java中,我们可以说

System.out.println(new MockFs().getName(Paths.get(""), myCont));

并且它将打印[usr, opt]。我们甚至可以传入继续的空实现。

最苛刻的情况发生在你事先不知道函数是否会自己挂起的时候。在这种情况下,一个好的方法是在调用点写下以下内容:

Object retVal = mockFs.getName(Paths.get(""), myCont);
if (retVal != IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
    myCont.resume((List<String>) retVal);
}

否则,您必须复制处理函数结果的代码。

 类似资料:
  • 如何在使用Kotlin的Spring Boot中正确初始化ConfigurationProperties? 目前我喜欢下面的例子: 但是它看起来很丑陋,实际上不是一个iable,foo是常量ue,应该在启动期间初始化,将来不会改变。

  • 我试图将库从Kotlin转换为Java,但这个方法限制了我: 如何在Java中实现

  • 问题内容: 我正在学习具有C ++和Java背景的Kotlin。我期待下面的打印,不。我知道这对应到。默认实现不比较每个成员,即和吗?如果是这样,它会不会看到字符串值相等(因为再次映射到字符串值)?显然,我在Kotlin中还没有涉及平等与身份相关的问题。 问题答案: 您描述的默认实现仅适用于数据类。不适用于从中继承实现的常规类,只需使对象与自身相等即可。

  • 这是正确的吗? 我可以找到一个相关的问题,但它是有参数的,我不能在没有params的情况下转换它。

  • 我正在尝试IntDef typedef将特定类型的参数限制为函数。但是当我使用Java使用IntDef时,它工作正常,但同时,它不适用于kotlin。以下是我的代码片段 - 在JAVA中- 在静态编程语言中- 在课堂上使用- 调用演示函数给我一个错误消息,说它必须是:< code>TransTypeJava之一。CASH,< code>TransTypeJava。通过传递< code>TransT