我有一个Kotlin
接口(interface)
interface MyKotlinInterface {
suspend fun mySuspendableMethod(): List<String>
}
然后我创建了一个Java
类,并实现了MyKotlinInterface
public class MyJavaImpl implements MyKotlinInterface {
@Nullable
@Override
public Object mySuspendableMethod(@NotNull Continuation<? super List<? extends String>> completion) {
return null;
}
}
IDE 没有显示错误,但是当我编译时出现以下错误
error: MyJavaImpl is not abstract and does not override abstract method mySuspendableMethod(Continuation<? super List>) in MyKotlinInterface public class MyJavaImpl implements MyKotlinInterface {
所以我的问题是
- 这有可能吗?
- 如果不可能,为什么 IDE 不显示任何错误?以及为什么 IDE 将
suspend
方法转换为Continuation
参数。
- 如果可能的话,为什么我会收到这个错误?以及如何解决?
更新:
我变了
@NotNull Continuation<? super List<? extends String>> completion
到
@NotNull Continuation completion
并且编译时错误消失了。
最佳答案
关于 suspend
方法如何在幕后在 Kotlin 中工作的最好 Material 可能是 Kotlin 存储库中的这个文件:
https://github.com/JetBrains/kotlin/pull/3709/files
正如您正确指出的那样,suspend
关键字通知 Kotlin 编译器将函数转换为状态机,或者用更熟悉的术语来说,转换为回调链。
为了在回调之间传递信息,我们需要一些东西来保存先前计算的结果。这是您看到的 Continuation
。在您的例子中,泛型类型是回调链中的最后一个调用应该产生的结果。
由于 JVM 中的泛型是一个编译时概念,因此通过完全删除它们可以规避问题,但并没有真正解决问题。
为什么 IDE 不警告编译问题?
AFAIK IntelliJ IDEA 使用自己的编译器版本来识别出现的问题。此编译器针对性能进行了优化,并且不处理某些边缘情况。
如何解决问题
在您的界面上放置一个类型:
interface MyKotlinInterface<T> {
suspend fun mySuspendableMethod(): List<T>
}
您的 Java 类必须稍作更改:
public class MyJavaImpl<T> implements MyKotlinInterface<T> {
@Nullable
@Override
public Object mySuspendableMethod(@NotNull Continuation<? super List<? extends T>> $completion) {
return List.of("A", "B");
}
}
但它会正常运行和编译:
fun main() = runBlocking {
val impl = MyJavaImpl<String>()
println(impl.mySuspendableMethod())
}
关于java - 如何在 Java 类中实现 Kotlin 挂起方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68032757/