Reputation: 11754
I have a Kotlin
interface
interface MyKotlinInterface {
suspend fun mySuspendableMethod(): List<String>
}
then I created a Java
class, and implemented MyKotlinInterface
public class MyJavaImpl implements MyKotlinInterface {
@Nullable
@Override
public Object mySuspendableMethod(@NotNull Continuation<? super List<? extends String>> completion) {
return null;
}
}
the IDE shows no error, but when I compile am getting below error
error: MyJavaImpl is not abstract and does not override abstract method mySuspendableMethod(Continuation<? super List>) in MyKotlinInterface public class MyJavaImpl implements MyKotlinInterface {
So my questions are
suspend
method to Continuation
param.UPDATE:
I've changed
@NotNull Continuation<? super List<? extends String>> completion
to
@NotNull Continuation completion
and the compile-time error has gone.
Upvotes: 4
Views: 1044
Reputation: 17721
Probably the best material on how suspend
methods work in Kotlin behind the scenes is this file in the Kotlin repo:
https://github.com/JetBrains/kotlin/pull/3709/files
As you've correctly noted, suspend
keyword informs Kotlin compiler to transform the function into a statemachine, or, in maybe a bit more familiar terms, into a chain of callbacks.
To pass information between callbacks we need something to hold the result of the previous computation. This is the Continuation
you see. The generic type, in your case List, is what the last call in the chain of callbacks should produce.
Since generics in JVM are a compile-time concept, by erasing them altogether you circumvented the issue, but not really solved it.
Why IDE doesn't alert regarding compilation issues?
AFAIK IntelliJ IDEA uses its own version of compiler in order to recognize the issues as they occur. This compiler is optimised for performance, and doesn't handle some edge cases.
How to solve the issue
Put a type on your interface:
interface MyKotlinInterface<T> {
suspend fun mySuspendableMethod(): List<T>
}
Your Java class will have to change slightly:
public class MyJavaImpl<T> implements MyKotlinInterface<T> {
@Nullable
@Override
public Object mySuspendableMethod(@NotNull Continuation<? super List<? extends T>> $completion) {
return List.of("A", "B");
}
}
But it will run and compile fine:
fun main() = runBlocking {
val impl = MyJavaImpl<String>()
println(impl.mySuspendableMethod())
}
Upvotes: 7