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.