I have an odd situation I’ve never run into before. At my company we have a mix of projects with most in Java but a growing number in Kotlin. So we have this existing application written in Java, and we are adding a library written in Kotlin.
The Kotlin code has a function argument that takes in a lambda expression. That lambda has this type, with the “params” argument being a map with values of “Any”:
(params: Map<String,Any>) -> List<Item>
In the Java code, we implement this lambda by taking “params” and passing them to a Java function:
params -> receiverFunction(params)
However, the Java function accepts a map argument with values of “Object”:
public List<Item> receiverFunction(final Map<String,Object> params)
I now get a compile error, where “params” in the Java lambda is seen as having type Map<String,capture of ?>
, which cannot be passed to Map<String,Object>
.
What is the recommended way to achieve this level of Java/Kotlin interoperability?
Advertisement
Answer
The Map you defined on the Kotlin side was a read-only Map, so the value types are marked out
. Kotlin’s out Any
is roughly equivalent to Java’s ? extends Object
. But since your receiverFunction
defines the value type as the more strict Object
, they are not a match.
Solution 1: Change Java value type to ?
, which is equivalent to ? extends object
.
Solution 2: Change the Kotlin parameter from Map to MutableMap.
If receiverFunction
doesn’t need to mutate the map (it probably doesn’t), Solution 1 is much preferred. And the Java method should probably have been written that way in the first place for better encapsulation, even without having to keep Kotlin in mind.