Hi! I am trying to call a `suspend fun` from Java,...
# coroutines
j
Hi! I am trying to call a
suspend fun
from Java, but I can't access any properties of
Result
- when implementing
Continuation
, I only get an
Object
in
resumeWith
. Can anybody help with that? 🙂
Copy code
service.myApiCall(10, new Continuation<List<String>>() {
            @NotNull
            @Override
            public CoroutineContext getContext() {
                 ...
            }

            @Override
            public void resumeWith(@NotNull Object result) {
                   // result should acutally be of type Result<List<String>>
            }
        });
m
Maybe it's because it is an inline class, so you just have to cast it to the actual List. But I have no idea how to access the exception from Java 🤔
👍 1
j
Yes, that's what I thought (although that's super weird). The thing is while casting works, I still can't access any properties then 😞
m
What did you cast it to?
d
You should be able to perform operations on the object through
Result.getValue(instance)
for example
I don't think that particular function exists
But the object is what the Result wraps, it's just inlined
If it's an exception then the exception is wrapped by another wrapper class in order to distinguish it
Look at static functions available on
Result
type
j
I'm not quite sure what you mean @Dico. I really can't call anything on
result
except for
equals
,
hashCode
and
toString
, even if I cast it 😕
d
I said static functions.
On the Jvm, that's a part of how inline classes are implemented. Static functions taking the wrapped value or reference as the first parameter.
If you cant find anything, it happens to be that, if there wasn't an error, the object will be null or a
List
, which is your continuation's
T
. However, if you rely on that, you're relying on implementation details of
Result
.
j
Right. Still, I don't understand why
resumeWith
is being called with an
Object
instead of my
T
. There seems to be a static method called
constructor-impl
on the class
Result
, but I can't call it from Java because of the dash, so this sadly doesn't help me.
d
If nothing else, this seems like a failure to consider java compatibility.
I tried it myself and, unfortunately, I can't figure it out either.
m
The wrapped value of Result is
Any?
So
Result<Whatever>
is
Object
in Java because it doesn't use the inline class's wrapper class.
d
Copy code
@SuppressWarnings("KotlinInternalInJava")
@Override
public void resumeWith(@NotNull Object o) {
    if (o instanceof Result.Failure) {
        Throwable exception = ((Result.Failure) o).exception;
    } else {
        List<String> result = (List<String>) o;
    }
}
👍 1
sadly, you have to do it like this.
m
The
@NotNull
seems to be wrong though
d
that's a good point. IntelliJ generated that.
Seems like a bug in IntelliJ.
😮 1
Maybe not, according to IntelliJ the super method's parameter is marked with
@NotNull
which is true if you consider the
Result
type, but not the erased type of
Any?
m
So it's wrong in the
Continuation
interface in Java? Makes sense
d
yeah, that's what I think
j
Thanks for trying! Isn't
resumeWith
called with a
Result
in any case? If I got it correctly, casting
Object o
to the
T
wouldn't work because it's still a Result.
d
It's a
Result
in Kotlin code, but because
Result
is an inline class, the erased type or the type that's visible from Java is the type of the only field that
Result
has.
that type is
Any?
or
@Nullable Object
, which is used as an intersection of
T
and
Result.Failure
.
j
Neat, thanks for the explanation!